Blockfile: Add generics, part 1

This commit is contained in:
zzz
2016-04-20 12:40:28 +00:00
parent 1a8847d177
commit 4d2c227b0d
18 changed files with 238 additions and 228 deletions

View File

@ -105,13 +105,13 @@ public class BlockfileNamingService extends DummyNamingService {
private String _version = "0"; private String _version = "0";
private boolean _needsUpgrade; private boolean _needsUpgrade;
private static final Serializer _infoSerializer = new PropertiesSerializer(); private static final Serializer<Properties> _infoSerializer = new PropertiesSerializer();
private static final Serializer _stringSerializer = new UTF8StringBytes(); private static final Serializer<String> _stringSerializer = new UTF8StringBytes();
private static final Serializer _destSerializerV1 = new DestEntrySerializer(); private static final Serializer<DestEntry> _destSerializerV1 = new DestEntrySerializer();
private static final Serializer _destSerializerV4 = new DestEntrySerializerV4(); private static final Serializer<DestEntry> _destSerializerV4 = new DestEntrySerializerV4();
// upgrade(), initExisting(), and initNew() will change this to _destSerializerV4 // upgrade(), initExisting(), and initNew() will change this to _destSerializerV4
private volatile Serializer _destSerializer = _destSerializerV1; private volatile Serializer<DestEntry> _destSerializer = _destSerializerV1;
private static final Serializer _hashIndexSerializer = new IntBytes(); private static final Serializer<Integer> _hashIndexSerializer = new IntBytes();
private static final String HOSTS_DB = "hostsdb.blockfile"; private static final String HOSTS_DB = "hostsdb.blockfile";
private static final String FALLBACK_LIST = "hosts.txt"; private static final String FALLBACK_LIST = "hosts.txt";
@ -1402,14 +1402,13 @@ public class BlockfileNamingService extends DummyNamingService {
* but if we threw a RuntimeException we would prevent access to entries later in * but if we threw a RuntimeException we would prevent access to entries later in
* the SkipSpan. * the SkipSpan.
*/ */
private static class DestEntrySerializer implements Serializer { private static class DestEntrySerializer implements Serializer<DestEntry> {
/** /**
* A format error on the properties is non-fatal (only the properties are lost) * A format error on the properties is non-fatal (only the properties are lost)
* A format error on the destination is fatal * A format error on the destination is fatal
*/ */
public byte[] getBytes(Object o) { public byte[] getBytes(DestEntry de) {
DestEntry de = (DestEntry) o;
ByteArrayOutputStream baos = new ByteArrayOutputStream(1024); ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
try { try {
try { try {
@ -1429,7 +1428,7 @@ public class BlockfileNamingService extends DummyNamingService {
} }
/** returns null on error */ /** returns null on error */
public Object construct(byte[] b) { public DestEntry construct(byte[] b) {
DestEntry rv = new DestEntry(); DestEntry rv = new DestEntry();
ByteArrayInputStream bais = new ByteArrayInputStream(b); ByteArrayInputStream bais = new ByteArrayInputStream(b);
try { try {
@ -1452,10 +1451,9 @@ public class BlockfileNamingService extends DummyNamingService {
* For multiple destinations per hostname * For multiple destinations per hostname
* @since 0.9.26 * @since 0.9.26
*/ */
private static class DestEntrySerializerV4 implements Serializer { private static class DestEntrySerializerV4 implements Serializer<DestEntry> {
public byte[] getBytes(Object o) { public byte[] getBytes(DestEntry de) {
DestEntry de = (DestEntry) o;
ByteArrayOutputStream baos = new ByteArrayOutputStream(1024); ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
int sz = de.destList != null ? de.destList.size() : 1; int sz = de.destList != null ? de.destList.size() : 1;
try { try {
@ -1487,7 +1485,7 @@ public class BlockfileNamingService extends DummyNamingService {
} }
/** returns null on error */ /** returns null on error */
public Object construct(byte[] b) { public DestEntry construct(byte[] b) {
DestEntry rv = new DestEntry(); DestEntry rv = new DestEntry();
ByteArrayInputStream bais = new ByteArrayInputStream(b); ByteArrayInputStream bais = new ByteArrayInputStream(b);
try { try {

View File

@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package net.metanotion.io; package net.metanotion.io;
public interface Serializer { public interface Serializer<T> {
public byte[] getBytes(Object o); public byte[] getBytes(T o);
public Object construct(byte[] b); public T construct(byte[] b);
} }

View File

@ -96,7 +96,7 @@ public class BlockFile implements Closeable {
/** I2P was the file locked when we opened it? */ /** I2P was the file locked when we opened it? */
private final boolean _wasMounted; private final boolean _wasMounted;
private final BSkipList metaIndex; private final BSkipList<String, Integer> metaIndex;
private boolean _isClosed; private boolean _isClosed;
/** cached list of free pages, only valid if freListStart > 0 */ /** cached list of free pages, only valid if freListStart > 0 */
private FreeListBlock flb; private FreeListBlock flb;
@ -322,7 +322,7 @@ public class BlockFile implements Closeable {
if (rai.canWrite()) if (rai.canWrite())
mount(); mount();
metaIndex = new BSkipList(spanSize, this, METAINDEX_PAGE, new StringBytes(), new IntBytes()); metaIndex = new BSkipList<String, Integer>(spanSize, this, METAINDEX_PAGE, new StringBytes(), new IntBytes());
} }
/** /**
@ -442,15 +442,15 @@ public class BlockFile implements Closeable {
* *
* @return null if not found * @return null if not found
*/ */
public BSkipList getIndex(String name, Serializer key, Serializer val) throws IOException { public <K extends Comparable<? super K>, V> BSkipList<K, V> getIndex(String name, Serializer<K> key, Serializer<V> val) throws IOException {
// added I2P // added I2P
BSkipList bsl = openIndices.get(name); BSkipList<K, V> bsl = (BSkipList<K, V>) openIndices.get(name);
if (bsl != null) if (bsl != null)
return bsl; return bsl;
Integer page = (Integer) metaIndex.get(name); Integer page = metaIndex.get(name);
if (page == null) { return null; } if (page == null) { return null; }
bsl = new BSkipList(spanSize, this, page.intValue(), key, val, true); bsl = new BSkipList<K, V>(spanSize, this, page.intValue(), key, val, true);
if (file.canWrite()) { if (file.canWrite()) {
log.info("Checking skiplist " + name + " in blockfile " + file); log.info("Checking skiplist " + name + " in blockfile " + file);
if (bsl.bslck(true, false)) if (bsl.bslck(true, false))
@ -468,12 +468,12 @@ public class BlockFile implements Closeable {
* *
* @throws IOException if already exists or other errors * @throws IOException if already exists or other errors
*/ */
public BSkipList makeIndex(String name, Serializer key, Serializer val) throws IOException { public <K extends Comparable<? super K>, V> BSkipList<K, V> makeIndex(String name, Serializer<K> key, Serializer<V> val) throws IOException {
if(metaIndex.get(name) != null) { throw new IOException("Index already exists"); } if(metaIndex.get(name) != null) { throw new IOException("Index already exists"); }
int page = allocPage(); int page = allocPage();
metaIndex.put(name, Integer.valueOf(page)); metaIndex.put(name, Integer.valueOf(page));
BSkipList.init(this, page, spanSize); BSkipList.init(this, page, spanSize);
BSkipList bsl = new BSkipList(spanSize, this, page, key, val, true); BSkipList<K, V> bsl = new BSkipList<K, V>(spanSize, this, page, key, val, true);
openIndices.put(name, bsl); openIndices.put(name, bsl);
return bsl; return bsl;
} }
@ -516,24 +516,24 @@ public class BlockFile implements Closeable {
* @throws IOException if it is open or on errors * @throws IOException if it is open or on errors
* @since 0.9.26 * @since 0.9.26
*/ */
public void reformatIndex(String name, Serializer oldKey, Serializer oldVal, public <K extends Comparable<? super K>, V> void reformatIndex(String name, Serializer<K> oldKey, Serializer<V> oldVal,
Serializer newKey, Serializer newVal) throws IOException { Serializer<K> newKey, Serializer<V> newVal) throws IOException {
if (openIndices.containsKey(name)) if (openIndices.containsKey(name))
throw new IOException("Cannot reformat open skiplist " + name); throw new IOException("Cannot reformat open skiplist " + name);
BSkipList old = getIndex(name, oldKey, oldVal); BSkipList<K, V> old = getIndex(name, oldKey, oldVal);
if (old == null) if (old == null)
return; return;
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
String tmpName = "---tmp---" + name + "---tmp---"; String tmpName = "---tmp---" + name + "---tmp---";
BSkipList tmp = makeIndex(tmpName, newKey, newVal); BSkipList<K, V> tmp = makeIndex(tmpName, newKey, newVal);
// It could be much more efficient to do this at the // It could be much more efficient to do this at the
// SkipSpan layer but that's way too hard. // SkipSpan layer but that's way too hard.
final int loop = 32; final int loop = 32;
List<Comparable> keys = new ArrayList<Comparable>(loop); List<K> keys = new ArrayList<K>(loop);
List<Object> vals = new ArrayList<Object>(loop); List<V> vals = new ArrayList<V>(loop);
while (true) { while (true) {
SkipIterator iter = old.iterator(); SkipIterator<K, V> iter = old.iterator();
for (int i = 0; iter.hasNext() && i < loop; i++) { for (int i = 0; iter.hasNext() && i < loop; i++) {
keys.add(iter.nextKey()); keys.add(iter.nextKey());
vals.add(iter.next()); vals.add(iter.next());
@ -555,7 +555,7 @@ public class BlockFile implements Closeable {
delIndex(name); delIndex(name);
closeIndex(name); closeIndex(name);
closeIndex(tmpName); closeIndex(tmpName);
Integer page = (Integer) metaIndex.get(tmpName); Integer page = metaIndex.get(tmpName);
metaIndex.put(name, page); metaIndex.put(name, page);
metaIndex.remove(tmpName); metaIndex.remove(tmpName);
if (log.shouldWarn()) if (log.shouldWarn())
@ -623,9 +623,15 @@ public class BlockFile implements Closeable {
try { try {
// This uses IdentityBytes, so the value class won't be right, but at least // This uses IdentityBytes, so the value class won't be right, but at least
// it won't fail the out-of-order check // it won't fail the out-of-order check
Serializer keyser = slname.equals("%%__REVERSE__%%") ? new IntBytes() : new UTF8StringBytes(); boolean fail;
BSkipList bsl = getIndex(slname, keyser, new IdentityBytes()); if (slname.equals("%%__REVERSE__%%")) {
if (bsl == null) { Serializer<Integer> keyser = new IntBytes();
fail = getIndex(slname, keyser, new IdentityBytes()) == null;
} else {
Serializer<String> keyser = new UTF8StringBytes();
fail = getIndex(slname, keyser, new IdentityBytes()) == null;
}
if (fail) {
log.error("Can't find list? " + slname); log.error("Can't find list? " + slname);
continue; continue;
} }

View File

@ -55,13 +55,13 @@ import net.i2p.util.Log;
* *
* Always fits on one page. * Always fits on one page.
*/ */
public class BSkipLevels extends SkipLevels { public class BSkipLevels<K extends Comparable<? super K>, V> extends SkipLevels<K, V> {
private static final long MAGIC = 0x42534c6576656c73l; // "BSLevels" private static final long MAGIC = 0x42534c6576656c73l; // "BSLevels"
static final int HEADER_LEN = 16; static final int HEADER_LEN = 16;
public final int levelPage; public final int levelPage;
public final int spanPage; public final int spanPage;
public final BlockFile bf; public final BlockFile bf;
private final BSkipList bsl; private final BSkipList<K, V> bsl;
private boolean isKilled; private boolean isKilled;
// the level pages, passed from the constructor to initializeLevels(), // the level pages, passed from the constructor to initializeLevels(),
// NOT kept up to date // NOT kept up to date
@ -73,7 +73,7 @@ public class BSkipLevels extends SkipLevels {
* after the constructor, unless it's a new empty * after the constructor, unless it's a new empty
* level and init() was previously called. * level and init() was previously called.
*/ */
public BSkipLevels(BlockFile bf, int levelPage, BSkipList bsl) throws IOException { public BSkipLevels(BlockFile bf, int levelPage, BSkipList<K, V> bsl) throws IOException {
this.levelPage = levelPage; this.levelPage = levelPage;
this.bf = bf; this.bf = bf;
this.bsl = bsl; this.bsl = bsl;
@ -97,7 +97,7 @@ public class BSkipLevels extends SkipLevels {
throw new IOException("No span found in cache???"); throw new IOException("No span found in cache???");
} }
this.levels = new BSkipLevels[maxLen]; this.levels = (BSkipLevels<K, V>[]) new BSkipLevels[maxLen];
if (bf.log.shouldLog(Log.DEBUG)) if (bf.log.shouldLog(Log.DEBUG))
bf.log.debug("Reading New BSkipLevels with " + nonNull + " / " + maxLen + " valid levels page " + levelPage + bf.log.debug("Reading New BSkipLevels with " + nonNull + " / " + maxLen + " valid levels page " + levelPage +
" in skiplist " + bsl); " in skiplist " + bsl);
@ -118,14 +118,14 @@ public class BSkipLevels extends SkipLevels {
* @since 0.9.20 * @since 0.9.20
*/ */
public void initializeLevels() { public void initializeLevels() {
List<BSkipLevels> toInit = new ArrayList<BSkipLevels>(32); List<BSkipLevels<K, V>> toInit = new ArrayList<BSkipLevels<K, V>>(32);
List<BSkipLevels> nextInit = new ArrayList<BSkipLevels>(32); List<BSkipLevels<K, V>> nextInit = new ArrayList<BSkipLevels<K, V>>(32);
initializeLevels(toInit); initializeLevels(toInit);
while (!toInit.isEmpty()) { while (!toInit.isEmpty()) {
for (BSkipLevels bsl : toInit) { for (BSkipLevels<K, V> bsl : toInit) {
bsl.initializeLevels(nextInit); bsl.initializeLevels(nextInit);
} }
List<BSkipLevels> tmp = toInit; List<BSkipLevels<K, V>> tmp = toInit;
toInit = nextInit; toInit = nextInit;
nextInit = tmp; nextInit = tmp;
nextInit.clear(); nextInit.clear();
@ -139,7 +139,7 @@ public class BSkipLevels extends SkipLevels {
* @param nextInit out parameter, next levels to initialize * @param nextInit out parameter, next levels to initialize
* @since 0.9.20 * @since 0.9.20
*/ */
private void initializeLevels(List<BSkipLevels> nextInit) { private void initializeLevels(List<BSkipLevels<K, V>> nextInit) {
boolean fail = false; boolean fail = false;
for(int i = 0; i < lps.length; i++) { for(int i = 0; i < lps.length; i++) {
int lp = lps[i]; int lp = lps[i];
@ -147,7 +147,7 @@ public class BSkipLevels extends SkipLevels {
levels[i] = bsl.levelHash.get(Integer.valueOf(lp)); levels[i] = bsl.levelHash.get(Integer.valueOf(lp));
if(levels[i] == null) { if(levels[i] == null) {
try { try {
BSkipLevels lev = new BSkipLevels(bf, lp, bsl); BSkipLevels<K, V> lev = new BSkipLevels<K, V>(bf, lp, bsl);
levels[i] = lev; levels[i] = lev;
nextInit.add(lev); nextInit.add(lev);
} catch (IOException ioe) { } catch (IOException ioe) {
@ -158,8 +158,8 @@ public class BSkipLevels extends SkipLevels {
continue; continue;
} }
} }
Comparable ourKey = key(); K ourKey = key();
Comparable nextKey = levels[i].key(); K nextKey = levels[i].key();
if (ourKey != null && nextKey != null && if (ourKey != null && nextKey != null &&
ourKey.compareTo(nextKey) >= 0) { ourKey.compareTo(nextKey) >= 0) {
bf.log.warn("Corrupt database, level out of order " + this + bf.log.warn("Corrupt database, level out of order " + this +
@ -215,9 +215,9 @@ public class BSkipLevels extends SkipLevels {
break; break;
} }
bf.file.writeShort(i); bf.file.writeShort(i);
bf.file.writeInt(((BSkipSpan) bottom).page); bf.file.writeInt(((BSkipSpan<K, V>) bottom).page);
for(int j = 0; j < i; j++) { for(int j = 0; j < i; j++) {
bf.file.writeInt(((BSkipLevels) levels[j]).levelPage); bf.file.writeInt(((BSkipLevels<K, V>) levels[j]).levelPage);
} }
} catch (IOException ioe) { throw new RuntimeException("Error writing to database", ioe); } } catch (IOException ioe) { throw new RuntimeException("Error writing to database", ioe); }
} }
@ -236,15 +236,15 @@ public class BSkipLevels extends SkipLevels {
} }
@Override @Override
public SkipLevels newInstance(int levels, SkipSpan ss, SkipList sl) { public SkipLevels<K, V> newInstance(int levels, SkipSpan<K, V> ss, SkipList<K, V> sl) {
try { try {
BSkipSpan bss = (BSkipSpan) ss; BSkipSpan<K, V> bss = (BSkipSpan<K, V>) ss;
BSkipList bsl = (BSkipList) sl; BSkipList<K, V> bsl = (BSkipList<K, V>) sl;
int page = bf.allocPage(); int page = bf.allocPage();
BSkipLevels.init(bf, page, bss.page, levels); BSkipLevels.init(bf, page, bss.page, levels);
if (bf.log.shouldLog(Log.DEBUG)) if (bf.log.shouldLog(Log.DEBUG))
bf.log.debug("New BSkipLevels height " + levels + " page " + page); bf.log.debug("New BSkipLevels height " + levels + " page " + page);
return new BSkipLevels(bf, page, bsl); return new BSkipLevels<K, V>(bf, page, bsl);
// do not need to call initLevels() here // do not need to call initLevels() here
} catch (IOException ioe) { throw new RuntimeException("Error creating database page", ioe); } } catch (IOException ioe) { throw new RuntimeException("Error creating database page", ioe); }
} }
@ -273,7 +273,7 @@ public class BSkipLevels extends SkipLevels {
* @since 0.8.8 * @since 0.8.8
*/ */
private boolean blvlfix() { private boolean blvlfix() {
TreeSet<SkipLevels> lvls = new TreeSet<SkipLevels>(new LevelComparator()); TreeSet<SkipLevels<K, V>> lvls = new TreeSet<SkipLevels<K, V>>(new LevelComparator<K, V>());
if (bf.log.shouldLog(Log.DEBUG)) if (bf.log.shouldLog(Log.DEBUG))
bf.log.debug("Starting level search"); bf.log.debug("Starting level search");
getAllLevels(this, lvls); getAllLevels(this, lvls);
@ -285,15 +285,15 @@ public class BSkipLevels extends SkipLevels {
} }
// traverse the levels, back-to-front // traverse the levels, back-to-front
boolean rv = false; boolean rv = false;
SkipLevels after = null; SkipLevels<K, V> after = null;
for (SkipLevels lv : lvls) { for (SkipLevels<K, V> lv : lvls) {
boolean modified = false; boolean modified = false;
if (bf.log.shouldLog(Log.DEBUG)) if (bf.log.shouldLog(Log.DEBUG))
bf.log.debug("Checking " + lv.print()); bf.log.debug("Checking " + lv.print());
if (after != null) { if (after != null) {
int min = Math.min(after.levels.length, lv.levels.length); int min = Math.min(after.levels.length, lv.levels.length);
for (int i = 0; i < min; i++) { for (int i = 0; i < min; i++) {
SkipLevels cur = lv.levels[i]; SkipLevels<K, V> cur = lv.levels[i];
if (cur != after) { if (cur != after) {
if (cur != null) if (cur != null)
bf.log.warn("Level " + i + " was wrong, fixing for " + lv.print()); bf.log.warn("Level " + i + " was wrong, fixing for " + lv.print());
@ -331,12 +331,12 @@ public class BSkipLevels extends SkipLevels {
* @param lvlSet out parameter, the result * @param lvlSet out parameter, the result
* @since 0.8.8 * @since 0.8.8
*/ */
private void getAllLevels(SkipLevels l, Set<SkipLevels> lvlSet) { private void getAllLevels(SkipLevels<K, V> l, Set<SkipLevels<K, V>> lvlSet) {
if (bf.log.shouldLog(Log.DEBUG)) if (bf.log.shouldLog(Log.DEBUG))
bf.log.debug("GAL " + l.print()); bf.log.debug("GAL " + l.print());
// Do level 0 without recursion, on the assumption everything is findable // Do level 0 without recursion, on the assumption everything is findable
// from the root // from the root
SkipLevels cur = l; SkipLevels<K, V> cur = l;
while (cur != null && lvlSet.add(cur)) { while (cur != null && lvlSet.add(cur)) {
if (bf.log.shouldLog(Log.DEBUG)) if (bf.log.shouldLog(Log.DEBUG))
bf.log.debug("Adding " + cur.print()); bf.log.debug("Adding " + cur.print());
@ -347,7 +347,7 @@ public class BSkipLevels extends SkipLevels {
// If there were no nulls at level 0 in the middle, // If there were no nulls at level 0 in the middle,
// i.e. there are no problems, this won't find anything // i.e. there are no problems, this won't find anything
for (int i = 1; i < l.levels.length; i++) { for (int i = 1; i < l.levels.length; i++) {
SkipLevels lv = l.levels[i]; SkipLevels<K, V> lv = l.levels[i];
if (lv != null && !lvlSet.contains(lv)) if (lv != null && !lvlSet.contains(lv))
getAllLevels(lv, lvlSet); getAllLevels(lv, lvlSet);
} }
@ -358,10 +358,10 @@ public class BSkipLevels extends SkipLevels {
* Sorts in REVERSE order. * Sorts in REVERSE order.
* @since 0.8.8 * @since 0.8.8
*/ */
private static class LevelComparator implements Comparator<SkipLevels>, Serializable { private static class LevelComparator<K extends Comparable<? super K>, V> implements Comparator<SkipLevels<K, V>>, Serializable {
public int compare(SkipLevels l, SkipLevels r) { public int compare(SkipLevels<K, V> l, SkipLevels<K, V> r) {
Comparable lk = l.key(); K lk = l.key();
Comparable rk = r.key(); K rk = r.key();
if (lk == null && rk == null) if (lk == null && rk == null)
return 0; return 0;
if (lk == null) if (lk == null)
@ -378,13 +378,13 @@ public class BSkipLevels extends SkipLevels {
* This needs work. * This needs work.
*/ */
@Override @Override
public boolean blvlck(boolean fix, int width, SkipLevels[] prevLevels) { public boolean blvlck(boolean fix, int width, SkipLevels<K, V>[] prevLevels) {
bf.log.warn(" Skip level at width " + width); bf.log.warn(" Skip level at width " + width);
bf.log.warn(" levels " + this.levels.length); bf.log.warn(" levels " + this.levels.length);
bf.log.warn(" first key " + this.key()); bf.log.warn(" first key " + this.key());
bf.log.warn(" spanPage " + this.spanPage); bf.log.warn(" spanPage " + this.spanPage);
bf.log.warn(" levelPage " + this.levelPage); bf.log.warn(" levelPage " + this.levelPage);
SkipLevels higher = null; SkipLevels<K, V> higher = null;
for (int i = levels.length - 1; i >= 0; i--) { for (int i = levels.length - 1; i >= 0; i--) {
if (levels[i] != null) { if (levels[i] != null) {
bf.log.info(" level " + i + " -> " + levels[i].key() + " "); bf.log.info(" level " + i + " -> " + levels[i].key() + " ");
@ -418,7 +418,7 @@ public class BSkipLevels extends SkipLevels {
} }
} }
} else { } else {
prevLevels = new SkipLevels[levels.length]; prevLevels = (SkipLevels<K, V>[]) new SkipLevels[levels.length];
System.arraycopy(levels, 0, prevLevels, 0, levels.length); System.arraycopy(levels, 0, prevLevels, 0, levels.length);
} }
if (levels[0] != null) if (levels[0] != null)

View File

@ -51,7 +51,7 @@ import net.i2p.util.Log;
* *
* Always fits on one page. * Always fits on one page.
*/ */
public class BSkipList extends SkipList implements Closeable { public class BSkipList<K extends Comparable<? super K>, V> extends SkipList<K, V> implements Closeable {
private static final long MAGIC = 0x536b69704c697374l; // "SkipList" private static final long MAGIC = 0x536b69704c697374l; // "SkipList"
public int firstSpanPage = 0; public int firstSpanPage = 0;
public int firstLevelPage = 0; public int firstLevelPage = 0;
@ -59,16 +59,16 @@ public class BSkipList extends SkipList implements Closeable {
public final BlockFile bf; public final BlockFile bf;
private boolean isClosed; private boolean isClosed;
final HashMap<Integer, BSkipSpan> spanHash = new HashMap<Integer, BSkipSpan>(); final HashMap<Integer, BSkipSpan<K, V>> spanHash = new HashMap<Integer, BSkipSpan<K, V>>();
final HashMap<Integer, SkipLevels> levelHash = new HashMap<Integer, SkipLevels>(); final HashMap<Integer, SkipLevels<K, V>> levelHash = new HashMap<Integer, SkipLevels<K, V>>();
private final boolean fileOnly; private final boolean fileOnly;
public BSkipList(int spanSize, BlockFile bf, int skipPage, Serializer key, Serializer val) throws IOException { public BSkipList(int spanSize, BlockFile bf, int skipPage, Serializer<K> key, Serializer<V> val) throws IOException {
this(spanSize, bf, skipPage, key, val, false); this(spanSize, bf, skipPage, key, val, false);
} }
public BSkipList(int spanSize, BlockFile bf, int skipPage, Serializer key, Serializer val, boolean fileOnly) throws IOException { public BSkipList(int spanSize, BlockFile bf, int skipPage, Serializer<K> key, Serializer<V> val, boolean fileOnly) throws IOException {
if(spanSize < 1) { throw new RuntimeException("Span size too small"); } if(spanSize < 1) { throw new RuntimeException("Span size too small"); }
this.skipPage = skipPage; this.skipPage = skipPage;
@ -89,10 +89,10 @@ public class BSkipList extends SkipList implements Closeable {
this.fileOnly = fileOnly; this.fileOnly = fileOnly;
if (fileOnly) if (fileOnly)
first = new IBSkipSpan(bf, this, firstSpanPage, key, val); first = new IBSkipSpan<K, V>(bf, this, firstSpanPage, key, val);
else else
first = new BSkipSpan(bf, this, firstSpanPage, key, val); first = new BSkipSpan<K, V>(bf, this, firstSpanPage, key, val);
BSkipLevels bstack = new BSkipLevels(bf, firstLevelPage, this); BSkipLevels<K, V> bstack = new BSkipLevels<K, V>(bf, firstLevelPage, this);
bstack.initializeLevels(); bstack.initializeLevels();
stack = bstack; stack = bstack;
int total = 0; int total = 0;
@ -199,33 +199,33 @@ public class BSkipList extends SkipList implements Closeable {
} }
@Override @Override
public SkipIterator iterator() { public SkipIterator<K, V> iterator() {
if (!this.fileOnly) if (!this.fileOnly)
return super.iterator(); return super.iterator();
return new IBSkipIterator(first, 0); return new IBSkipIterator<K, V>(first, 0);
} }
@Override @Override
public SkipIterator min() { public SkipIterator<K, V> min() {
return iterator(); return iterator();
} }
@Override @Override
public SkipIterator max() { public SkipIterator<K, V> max() {
if (!this.fileOnly) if (!this.fileOnly)
return super.max(); return super.max();
SkipSpan ss = stack.getEnd(); SkipSpan<K, V> ss = stack.getEnd();
return new IBSkipIterator(ss, ss.nKeys - 1); return new IBSkipIterator<K, V>(ss, ss.nKeys - 1);
} }
@Override @Override
public SkipIterator find(Comparable key) { public SkipIterator<K, V> find(K key) {
if (!this.fileOnly) if (!this.fileOnly)
return super.find(key); return super.find(key);
int[] search = new int[1]; int[] search = new int[1];
SkipSpan ss = stack.getSpan(stack.levels.length - 1, key, search); SkipSpan<K, V> ss = stack.getSpan(stack.levels.length - 1, key, search);
if(search[0] < 0) { search[0] = -1 * (search[0] + 1); } if(search[0] < 0) { search[0] = -1 * (search[0] + 1); }
return new IBSkipIterator(ss, search[0]); return new IBSkipIterator<K, V>(ss, search[0]);
} }
/** /**

View File

@ -59,19 +59,19 @@ import net.i2p.util.Log;
* next overflow page (unsigned int) * next overflow page (unsigned int)
*</pre> *</pre>
*/ */
public class BSkipSpan extends SkipSpan { public class BSkipSpan<K extends Comparable<? super K>, V> extends SkipSpan<K, V> {
protected static final int MAGIC = 0x5370616e; // "Span" protected static final int MAGIC = 0x5370616e; // "Span"
protected static final int HEADER_LEN = 20; protected static final int HEADER_LEN = 20;
public static final int CONT_HEADER_LEN = 8; public static final int CONT_HEADER_LEN = 8;
protected final BlockFile bf; protected final BlockFile bf;
private final BSkipList bsl; private final BSkipList<K, V> bsl;
protected int page; protected int page;
protected int overflowPage; protected int overflowPage;
protected int prevPage; protected int prevPage;
protected int nextPage = 0; protected int nextPage = 0;
protected Serializer keySer; protected Serializer<K> keySer;
protected Serializer valSer; protected Serializer<V> valSer;
// I2P // I2P
protected int spanSize; protected int spanSize;
@ -88,11 +88,11 @@ public class BSkipSpan extends SkipSpan {
} }
@Override @Override
public SkipSpan newInstance(SkipList sl) { public SkipSpan<K, V> newInstance(SkipList<K, V> sl) {
try { try {
int newPage = bf.allocPage(); int newPage = bf.allocPage();
init(bf, newPage, bf.spanSize); init(bf, newPage, bf.spanSize);
return new BSkipSpan(bf, (BSkipList) sl, newPage, keySer, valSer); return new BSkipSpan<K, V>(bf, (BSkipList<K, V>) sl, newPage, keySer, valSer);
} catch (IOException ioe) { throw new RuntimeException("Error creating database page", ioe); } } catch (IOException ioe) { throw new RuntimeException("Error creating database page", ioe); }
} }
@ -237,7 +237,8 @@ public class BSkipSpan extends SkipSpan {
//bsl.flush(); //bsl.flush();
} }
private static void load(BSkipSpan bss, BlockFile bf, BSkipList bsl, int spanPage, Serializer key, Serializer val) throws IOException { private static <X extends Comparable<? super X>, Y> void load(BSkipSpan<X, Y> bss, BlockFile bf, BSkipList<X, Y> bsl,
int spanPage, Serializer<X> key, Serializer<Y> val) throws IOException {
loadInit(bss, bf, bsl, spanPage, key, val); loadInit(bss, bf, bsl, spanPage, key, val);
bss.loadData(); bss.loadData();
} }
@ -246,7 +247,8 @@ public class BSkipSpan extends SkipSpan {
* I2P - first half of load() * I2P - first half of load()
* Only read the span headers * Only read the span headers
*/ */
protected static void loadInit(BSkipSpan bss, BlockFile bf, BSkipList bsl, int spanPage, Serializer key, Serializer val) throws IOException { protected static <X extends Comparable<? super X>, Y> void loadInit(BSkipSpan<X, Y> bss, BlockFile bf, BSkipList<X, Y> bsl,
int spanPage, Serializer<X> key, Serializer<Y> val) throws IOException {
if (bss.isKilled) if (bss.isKilled)
throw new IOException("Already killed!! " + bss); throw new IOException("Already killed!! " + bss);
bss.page = spanPage; bss.page = spanPage;
@ -288,8 +290,8 @@ public class BSkipSpan extends SkipSpan {
protected void loadData(boolean flushOnError) throws IOException { protected void loadData(boolean flushOnError) throws IOException {
if (isKilled) if (isKilled)
throw new IOException("Already killed!! " + this); throw new IOException("Already killed!! " + this);
this.keys = new Comparable[this.spanSize]; this.keys = (K[]) new Comparable[this.spanSize];
this.vals = new Object[this.spanSize]; this.vals = (V[]) new Object[this.spanSize];
int ksz, vsz; int ksz, vsz;
int curPage = this.page; int curPage = this.page;
@ -327,7 +329,7 @@ public class BSkipSpan extends SkipSpan {
break; break;
} }
// System.out.println("i=" + i + ", Page " + curPage + ", offset " + pageCounter[0] + " ksz " + ksz + " vsz " + vsz); // System.out.println("i=" + i + ", Page " + curPage + ", offset " + pageCounter[0] + " ksz " + ksz + " vsz " + vsz);
this.keys[i] = (Comparable) this.keySer.construct(k); this.keys[i] = this.keySer.construct(k);
this.vals[i] = this.valSer.construct(v); this.vals[i] = this.valSer.construct(v);
// Drop bad entry without throwing exception // Drop bad entry without throwing exception
if (this.keys[i] == null || this.vals[i] == null) { if (this.keys[i] == null || this.vals[i] == null) {
@ -377,31 +379,31 @@ public class BSkipSpan extends SkipSpan {
} }
} }
protected BSkipSpan(BlockFile bf, BSkipList bsl) { protected BSkipSpan(BlockFile bf, BSkipList<K, V> bsl) {
this.bf = bf; this.bf = bf;
this.bsl = bsl; this.bsl = bsl;
} }
public BSkipSpan(BlockFile bf, BSkipList bsl, int spanPage, Serializer key, Serializer val) throws IOException { public BSkipSpan(BlockFile bf, BSkipList<K, V> bsl, int spanPage, Serializer<K> key, Serializer<V> val) throws IOException {
this.bf = bf; this.bf = bf;
this.bsl = bsl; this.bsl = bsl;
BSkipSpan.load(this, bf, bsl, spanPage, key, val); BSkipSpan.load(this, bf, bsl, spanPage, key, val);
this.next = null; this.next = null;
this.prev = null; this.prev = null;
BSkipSpan bss = this; BSkipSpan<K, V> bss = this;
// findbugs ok (set in load() above) // findbugs ok (set in load() above)
int np = nextPage; int np = nextPage;
while(np != 0) { while(np != 0) {
BSkipSpan temp = bsl.spanHash.get(Integer.valueOf(np)); BSkipSpan<K, V> temp = bsl.spanHash.get(Integer.valueOf(np));
if(temp != null) { if(temp != null) {
bss.next = temp; bss.next = temp;
break; break;
} }
bss.next = new BSkipSpan(bf, bsl); bss.next = new BSkipSpan<K, V>(bf, bsl);
bss.next.next = null; bss.next.next = null;
bss.next.prev = bss; bss.next.prev = bss;
bss = (BSkipSpan) bss.next; bss = (BSkipSpan<K, V>) bss.next;
BSkipSpan.load(bss, bf, bsl, np, key, val); BSkipSpan.load(bss, bf, bsl, np, key, val);
np = bss.nextPage; np = bss.nextPage;
@ -411,15 +413,15 @@ public class BSkipSpan extends SkipSpan {
bss = this; bss = this;
np = prevPage; np = prevPage;
while(np != 0) { while(np != 0) {
BSkipSpan temp = bsl.spanHash.get(Integer.valueOf(np)); BSkipSpan<K, V> temp = bsl.spanHash.get(Integer.valueOf(np));
if(temp != null) { if(temp != null) {
bss.prev = temp; bss.prev = temp;
break; break;
} }
bss.prev = new BSkipSpan(bf, bsl); bss.prev = new BSkipSpan<K, V>(bf, bsl);
bss.prev.next = bss; bss.prev.next = bss;
bss.prev.prev = null; bss.prev.prev = null;
bss = (BSkipSpan) bss.prev; bss = (BSkipSpan<K, V>) bss.prev;
BSkipSpan.load(bss, bf, bsl, np, key, val); BSkipSpan.load(bss, bf, bsl, np, key, val);
np = bss.prevPage; np = bss.prevPage;

View File

@ -41,9 +41,9 @@ import net.metanotion.util.skiplist.SkipSpan;
If the caller does not iterate all the way through, the last span If the caller does not iterate all the way through, the last span
will remain in memory. will remain in memory.
*/ */
public class IBSkipIterator extends SkipIterator { public class IBSkipIterator<K extends Comparable<? super K>, V> extends SkipIterator<K, V> {
public IBSkipIterator(SkipSpan ss, int index) { public IBSkipIterator(SkipSpan<K, V> ss, int index) {
super(ss, index); super(ss, index);
} }
@ -53,8 +53,8 @@ public class IBSkipIterator extends SkipIterator {
* @throws RuntimeException on IOE * @throws RuntimeException on IOE
*/ */
@Override @Override
public Object next() { public V next() {
Object o; V o;
if(index < ss.nKeys) { if(index < ss.nKeys) {
if (ss.vals == null) { if (ss.vals == null) {
try { try {
@ -90,7 +90,7 @@ public class IBSkipIterator extends SkipIterator {
* @throws RuntimeException on IOE * @throws RuntimeException on IOE
*/ */
@Override @Override
public Comparable nextKey() { public K nextKey() {
if(index < ss.nKeys) { if(index < ss.nKeys) {
if (ss.keys == null) { if (ss.keys == null) {
try { try {
@ -110,7 +110,7 @@ public class IBSkipIterator extends SkipIterator {
* @throws RuntimeException on IOE * @throws RuntimeException on IOE
*/ */
@Override @Override
public Object previous() { public V previous() {
if(index > 0) { if(index > 0) {
index--; index--;
} else if(ss.prev != null) { } else if(ss.prev != null) {

View File

@ -54,21 +54,21 @@ import net.i2p.util.Log;
* *
* @author zzz * @author zzz
*/ */
public class IBSkipSpan extends BSkipSpan { public class IBSkipSpan<K extends Comparable<? super K>, V> extends BSkipSpan<K, V> {
private Comparable firstKey; private K firstKey;
@Override @Override
public SkipSpan newInstance(SkipList sl) { public SkipSpan<K, V> newInstance(SkipList<K, V> sl) {
if (bf.log.shouldLog(Log.DEBUG)) if (bf.log.shouldLog(Log.DEBUG))
bf.log.debug("Splitting page " + this.page + " containing " + this.nKeys + '/' + this.spanSize); bf.log.debug("Splitting page " + this.page + " containing " + this.nKeys + '/' + this.spanSize);
try { try {
int newPage = bf.allocPage(); int newPage = bf.allocPage();
init(bf, newPage, bf.spanSize); init(bf, newPage, bf.spanSize);
SkipSpan rv = new IBSkipSpan(bf, (BSkipList) sl, newPage, keySer, valSer); SkipSpan<K, V> rv = new IBSkipSpan<K, V>(bf, (BSkipList<K, V>) sl, newPage, keySer, valSer);
// this is called after a split, so we need the data arrays initialized // this is called after a split, so we need the data arrays initialized
rv.keys = new Comparable[bf.spanSize]; rv.keys = (K[]) new Comparable[bf.spanSize];
rv.vals = new Object[bf.spanSize]; rv.vals = (V[]) new Object[bf.spanSize];
return rv; return rv;
} catch (IOException ioe) { throw new RuntimeException("Error creating database page", ioe); } } catch (IOException ioe) { throw new RuntimeException("Error creating database page", ioe); }
} }
@ -125,7 +125,7 @@ public class IBSkipSpan extends BSkipSpan {
pageCounter[0] +=4; pageCounter[0] +=4;
byte[] k = new byte[ksz]; byte[] k = new byte[ksz];
curPage = this.bf.readMultiPageData(k, curPage, pageCounter, curNextPage); curPage = this.bf.readMultiPageData(k, curPage, pageCounter, curNextPage);
this.firstKey = (Comparable) this.keySer.construct(k); this.firstKey = this.keySer.construct(k);
if (this.firstKey == null) { if (this.firstKey == null) {
bf.log.error("Null deserialized first key in page " + curPage); bf.log.error("Null deserialized first key in page " + curPage);
repair(1); repair(1);
@ -160,7 +160,7 @@ public class IBSkipSpan extends BSkipSpan {
/** /**
* Linear search through the span in the file for the value. * Linear search through the span in the file for the value.
*/ */
private Object getData(Comparable key) throws IOException { private V getData(K key) throws IOException {
seekData(); seekData();
int curPage = this.page; int curPage = this.page;
int[] curNextPage = new int[1]; int[] curNextPage = new int[1];
@ -194,7 +194,7 @@ public class IBSkipSpan extends BSkipSpan {
break; break;
} }
//System.out.println("i=" + i + ", Page " + curPage + ", offset " + pageCounter[0] + " ksz " + ksz + " vsz " + vsz); //System.out.println("i=" + i + ", Page " + curPage + ", offset " + pageCounter[0] + " ksz " + ksz + " vsz " + vsz);
Comparable ckey = (Comparable) this.keySer.construct(k); K ckey = this.keySer.construct(k);
if (ckey == null) { if (ckey == null) {
// skip the value and keep going // skip the value and keep going
curPage = this.bf.skipMultiPageBytes(vsz, curPage, pageCounter, curNextPage); curPage = this.bf.skipMultiPageBytes(vsz, curPage, pageCounter, curNextPage);
@ -213,7 +213,7 @@ public class IBSkipSpan extends BSkipSpan {
lostEntries(i, curPage); lostEntries(i, curPage);
break; break;
} }
Object rv = this.valSer.construct(v); V rv = this.valSer.construct(v);
if (rv == null) { if (rv == null) {
bf.log.error("Null deserialized value in entry " + i + " page " + curPage + bf.log.error("Null deserialized value in entry " + i + " page " + curPage +
" key=" + ckey); " key=" + ckey);
@ -252,11 +252,11 @@ public class IBSkipSpan extends BSkipSpan {
*****/ *****/
} }
private IBSkipSpan(BlockFile bf, BSkipList bsl) { private IBSkipSpan(BlockFile bf, BSkipList<K, V> bsl) {
super(bf, bsl); super(bf, bsl);
} }
public IBSkipSpan(BlockFile bf, BSkipList bsl, int spanPage, Serializer key, Serializer val) throws IOException { public IBSkipSpan(BlockFile bf, BSkipList<K, V> bsl, int spanPage, Serializer<K> key, Serializer<V> val) throws IOException {
super(bf, bsl); super(bf, bsl);
if (bf.log.shouldLog(Log.DEBUG)) if (bf.log.shouldLog(Log.DEBUG))
bf.log.debug("New ibss page " + spanPage); bf.log.debug("New ibss page " + spanPage);
@ -265,24 +265,24 @@ public class IBSkipSpan extends BSkipSpan {
this.next = null; this.next = null;
this.prev = null; this.prev = null;
IBSkipSpan bss = this; IBSkipSpan<K, V> bss = this;
IBSkipSpan temp; IBSkipSpan<K, V> temp;
int np = nextPage; int np = nextPage;
while(np != 0) { while(np != 0) {
temp = (IBSkipSpan) bsl.spanHash.get(Integer.valueOf(np)); temp = (IBSkipSpan<K, V>) bsl.spanHash.get(Integer.valueOf(np));
if(temp != null) { if(temp != null) {
bss.next = temp; bss.next = temp;
break; break;
} }
bss.next = new IBSkipSpan(bf, bsl); bss.next = new IBSkipSpan<K, V>(bf, bsl);
bss.next.next = null; bss.next.next = null;
bss.next.prev = bss; bss.next.prev = bss;
Comparable previousFirstKey = bss.firstKey; K previousFirstKey = bss.firstKey;
bss = (IBSkipSpan) bss.next; bss = (IBSkipSpan<K, V>) bss.next;
BSkipSpan.loadInit(bss, bf, bsl, np, key, val); BSkipSpan.loadInit(bss, bf, bsl, np, key, val);
bss.loadFirstKey(); bss.loadFirstKey();
Comparable nextFirstKey = bss.firstKey; K nextFirstKey = bss.firstKey;
if (previousFirstKey == null || nextFirstKey == null || if (previousFirstKey == null || nextFirstKey == null ||
previousFirstKey.compareTo(nextFirstKey) >= 0) { previousFirstKey.compareTo(nextFirstKey) >= 0) {
// TODO remove, but if we are at the bottom of a level // TODO remove, but if we are at the bottom of a level
@ -299,20 +299,20 @@ public class IBSkipSpan extends BSkipSpan {
bss = this; bss = this;
np = prevPage; np = prevPage;
while(np != 0) { while(np != 0) {
temp = (IBSkipSpan) bsl.spanHash.get(Integer.valueOf(np)); temp = (IBSkipSpan<K, V>) bsl.spanHash.get(Integer.valueOf(np));
if(temp != null) { if(temp != null) {
bss.prev = temp; bss.prev = temp;
break; break;
} }
bss.prev = new IBSkipSpan(bf, bsl); bss.prev = new IBSkipSpan<K, V>(bf, bsl);
bss.prev.next = bss; bss.prev.next = bss;
bss.prev.prev = null; bss.prev.prev = null;
Comparable nextFirstKey = bss.firstKey; K nextFirstKey = bss.firstKey;
bss = (IBSkipSpan) bss.prev; bss = (IBSkipSpan<K, V>) bss.prev;
BSkipSpan.loadInit(bss, bf, bsl, np, key, val); BSkipSpan.loadInit(bss, bf, bsl, np, key, val);
bss.loadFirstKey(); bss.loadFirstKey();
Comparable previousFirstKey = bss.firstKey; K previousFirstKey = bss.firstKey;
if (previousFirstKey == null || nextFirstKey == null || if (previousFirstKey == null || nextFirstKey == null ||
previousFirstKey.compareTo(nextFirstKey) >= 0) { previousFirstKey.compareTo(nextFirstKey) >= 0) {
// TODO remove, but if we are at the bottom of a level // TODO remove, but if we are at the bottom of a level
@ -330,7 +330,7 @@ public class IBSkipSpan extends BSkipSpan {
* Does not call super, we always store first key here * Does not call super, we always store first key here
*/ */
@Override @Override
public Comparable firstKey() { public K firstKey() {
return this.firstKey; return this.firstKey;
} }
@ -339,13 +339,13 @@ public class IBSkipSpan extends BSkipSpan {
* This is called only via SkipList.find() * This is called only via SkipList.find()
*/ */
@Override @Override
public SkipSpan getSpan(Comparable key, int[] search) { public SkipSpan<K, V> getSpan(K key, int[] search) {
try { try {
seekAndLoadData(); seekAndLoadData();
} catch (IOException ioe) { } catch (IOException ioe) {
throw new RuntimeException("Error reading database", ioe); throw new RuntimeException("Error reading database", ioe);
} }
SkipSpan rv = super.getSpan(key, search); SkipSpan<K, V> rv = super.getSpan(key, search);
this.keys = null; this.keys = null;
this.vals = null; this.vals = null;
return rv; return rv;
@ -355,7 +355,7 @@ public class IBSkipSpan extends BSkipSpan {
* Linear search if in file, Binary search if in memory * Linear search if in file, Binary search if in memory
*/ */
@Override @Override
public Object get(Comparable key) { public V get(K key) {
try { try {
if (nKeys == 0) { return null; } if (nKeys == 0) { return null; }
if (this.next != null && this.next.firstKey().compareTo(key) <= 0) if (this.next != null && this.next.firstKey().compareTo(key) <= 0)
@ -370,13 +370,13 @@ public class IBSkipSpan extends BSkipSpan {
* Load whole span from file, do the operation, flush out, then null out in-memory data again. * Load whole span from file, do the operation, flush out, then null out in-memory data again.
*/ */
@Override @Override
public SkipSpan put(Comparable key, Object val, SkipList sl) { public SkipSpan<K, V> put(K key, V val, SkipList<K, V> sl) {
try { try {
seekAndLoadData(); seekAndLoadData();
} catch (IOException ioe) { } catch (IOException ioe) {
throw new RuntimeException("Error reading database", ioe); throw new RuntimeException("Error reading database", ioe);
} }
SkipSpan rv = super.put(key, val, sl); SkipSpan<K, V> rv = super.put(key, val, sl);
// flush() nulls out the data // flush() nulls out the data
return rv; return rv;
} }
@ -385,7 +385,7 @@ public class IBSkipSpan extends BSkipSpan {
* Load whole span from file, do the operation, flush out, then null out in-memory data again. * Load whole span from file, do the operation, flush out, then null out in-memory data again.
*/ */
@Override @Override
public Object[] remove(Comparable key, SkipList sl) { public Object[] remove(K key, SkipList<K, V> sl) {
if (bf.log.shouldLog(Log.DEBUG)) if (bf.log.shouldLog(Log.DEBUG))
bf.log.debug("Remove " + key + " in " + this); bf.log.debug("Remove " + key + " in " + this);
if (nKeys <= 0) if (nKeys <= 0)

View File

@ -35,11 +35,11 @@ import net.metanotion.io.Serializer;
* Will never return null. * Will never return null.
* Added by I2P. * Added by I2P.
*/ */
public class IdentityBytes implements Serializer { public class IdentityBytes implements Serializer<byte[]> {
/** @return byte[] */ /** @return byte[] */
public byte[] getBytes(Object o) { return (byte[])o; } public byte[] getBytes(byte[] o) { return o; }
/** @return b */ /** @return b */
public Object construct(byte[] b) { return b; } public byte[] construct(byte[] b) { return b; }
} }

View File

@ -30,10 +30,10 @@ package net.metanotion.io.data;
import net.metanotion.io.Serializer; import net.metanotion.io.Serializer;
public class IntBytes implements Serializer { public class IntBytes implements Serializer<Integer> {
public byte[] getBytes(Object o) { public byte[] getBytes(Integer o) {
byte[] b = new byte[4]; byte[] b = new byte[4];
int v = ((Integer) o).intValue(); int v = o.intValue();
b[0] = (byte)(0xff & (v >> 24)); b[0] = (byte)(0xff & (v >> 24));
b[1] = (byte)(0xff & (v >> 16)); b[1] = (byte)(0xff & (v >> 16));
b[2] = (byte)(0xff & (v >> 8)); b[2] = (byte)(0xff & (v >> 8));
@ -41,7 +41,7 @@ public class IntBytes implements Serializer {
return b; return b;
} }
public Object construct(byte[] b) { public Integer construct(byte[] b) {
int v = (((b[0] & 0xff) << 24) | int v = (((b[0] & 0xff) << 24) |
((b[1] & 0xff) << 16) | ((b[1] & 0xff) << 16) |
((b[2] & 0xff) << 8) | ((b[2] & 0xff) << 8) |

View File

@ -30,10 +30,10 @@ package net.metanotion.io.data;
import net.metanotion.io.Serializer; import net.metanotion.io.Serializer;
public class LongBytes implements Serializer { public class LongBytes implements Serializer<Long> {
public byte[] getBytes(Object o) { public byte[] getBytes(Long o) {
byte[] b = new byte[8]; byte[] b = new byte[8];
long v = ((Long) o).longValue(); long v = o.longValue();
b[0] = (byte)(0xff & (v >> 56)); b[0] = (byte)(0xff & (v >> 56));
b[1] = (byte)(0xff & (v >> 48)); b[1] = (byte)(0xff & (v >> 48));
b[2] = (byte)(0xff & (v >> 40)); b[2] = (byte)(0xff & (v >> 40));
@ -45,7 +45,7 @@ public class LongBytes implements Serializer {
return b; return b;
} }
public Object construct(byte[] b) { public Long construct(byte[] b) {
long v =(((long)(b[0] & 0xff) << 56) | long v =(((long)(b[0] & 0xff) << 56) |
((long)(b[1] & 0xff) << 48) | ((long)(b[1] & 0xff) << 48) |
((long)(b[2] & 0xff) << 40) | ((long)(b[2] & 0xff) << 40) |

View File

@ -30,7 +30,7 @@ package net.metanotion.io.data;
import net.metanotion.io.Serializer; import net.metanotion.io.Serializer;
public class NullBytes implements Serializer { public class NullBytes implements Serializer<Object> {
public byte[] getBytes(Object o) { return null; } public byte[] getBytes(Object o) { return null; }
public Object construct(byte[] b) { return null; } public Object construct(byte[] b) { return null; }
} }

View File

@ -32,14 +32,14 @@ import java.io.UnsupportedEncodingException;
import net.metanotion.io.Serializer; import net.metanotion.io.Serializer;
public class StringBytes implements Serializer { public class StringBytes implements Serializer<String> {
public byte[] getBytes(Object o) { public byte[] getBytes(String o) {
try { try {
return ((String) o).getBytes("US-ASCII"); return o.getBytes("US-ASCII");
} catch (UnsupportedEncodingException uee) { throw new Error("Unsupported Encoding"); } } catch (UnsupportedEncodingException uee) { throw new Error("Unsupported Encoding"); }
} }
public Object construct(byte[] b) { public String construct(byte[] b) {
try { try {
return new String(b, "US-ASCII"); return new String(b, "US-ASCII");
} catch (UnsupportedEncodingException uee) { throw new Error("Unsupported Encoding"); } } catch (UnsupportedEncodingException uee) { throw new Error("Unsupported Encoding"); }

View File

@ -35,14 +35,14 @@ import net.metanotion.io.Serializer;
/** /**
* Added by I2P * Added by I2P
*/ */
public class UTF8StringBytes implements Serializer { public class UTF8StringBytes implements Serializer<String> {
public byte[] getBytes(Object o) { public byte[] getBytes(String o) {
try { try {
return ((String) o).getBytes("UTF-8"); return o.getBytes("UTF-8");
} catch (UnsupportedEncodingException uee) { throw new Error("Unsupported Encoding"); } } catch (UnsupportedEncodingException uee) { throw new Error("Unsupported Encoding"); }
} }
public Object construct(byte[] b) { public String construct(byte[] b) {
try { try {
return new String(b, "UTF-8"); return new String(b, "UTF-8");
} catch (UnsupportedEncodingException uee) { throw new Error("Unsupported Encoding"); } } catch (UnsupportedEncodingException uee) { throw new Error("Unsupported Encoding"); }

View File

@ -39,12 +39,13 @@ import java.util.NoSuchElementException;
To be clear, this is an iterator through the values. To be clear, this is an iterator through the values.
To get the key, call nextKey() BEFORE calling next(). To get the key, call nextKey() BEFORE calling next().
*/ */
public class SkipIterator implements ListIterator { public class SkipIterator<K extends Comparable<? super K>, V> implements ListIterator<V> {
protected SkipSpan ss; protected SkipSpan<K, V> ss;
protected int index; protected int index;
protected SkipIterator() { } protected SkipIterator() { }
public SkipIterator(SkipSpan ss, int index) {
public SkipIterator(SkipSpan<K, V> ss, int index) {
if(ss==null) { throw new NullPointerException(); } if(ss==null) { throw new NullPointerException(); }
this.ss = ss; this.ss = ss;
this.index = index; this.index = index;
@ -59,8 +60,8 @@ public class SkipIterator implements ListIterator {
* @return the next value, and advances the index * @return the next value, and advances the index
* @throws NoSuchElementException * @throws NoSuchElementException
*/ */
public Object next() { public V next() {
Object o; V o;
if(index < ss.nKeys) { if(index < ss.nKeys) {
o = ss.vals[index]; o = ss.vals[index];
} else { } else {
@ -83,7 +84,7 @@ public class SkipIterator implements ListIterator {
* @return the key for which the value will be returned in the subsequent call to next() * @return the key for which the value will be returned in the subsequent call to next()
* @throws NoSuchElementException * @throws NoSuchElementException
*/ */
public Comparable nextKey() { public K nextKey() {
if(index < ss.nKeys) { return ss.keys[index]; } if(index < ss.nKeys) { return ss.keys[index]; }
throw new NoSuchElementException(); throw new NoSuchElementException();
} }
@ -98,7 +99,7 @@ public class SkipIterator implements ListIterator {
* @return the previous value, and decrements the index * @return the previous value, and decrements the index
* @throws NoSuchElementException * @throws NoSuchElementException
*/ */
public Object previous() { public V previous() {
if(index > 0) { if(index > 0) {
index--; index--;
} else if(ss.prev != null) { } else if(ss.prev != null) {
@ -111,9 +112,9 @@ public class SkipIterator implements ListIterator {
// Optional methods // Optional methods
public void add(Object o) { throw new UnsupportedOperationException(); } public void add(V o) { throw new UnsupportedOperationException(); }
public void remove() { throw new UnsupportedOperationException(); } public void remove() { throw new UnsupportedOperationException(); }
public void set(Object o) { throw new UnsupportedOperationException(); } public void set(V o) { throw new UnsupportedOperationException(); }
public int nextIndex() { throw new UnsupportedOperationException(); } public int nextIndex() { throw new UnsupportedOperationException(); }
public int previousIndex() { throw new UnsupportedOperationException(); } public int previousIndex() { throw new UnsupportedOperationException(); }

View File

@ -35,7 +35,7 @@ import net.metanotion.io.block.BlockFile;
import net.i2p.I2PAppContext; import net.i2p.I2PAppContext;
import net.i2p.util.Log; import net.i2p.util.Log;
public class SkipLevels implements Flushable { public class SkipLevels<K extends Comparable<? super K>, V> implements Flushable {
/** We can't have more than 2**32 pages */ /** We can't have more than 2**32 pages */
public static final int MAX_SIZE = 32; public static final int MAX_SIZE = 32;
@ -45,12 +45,15 @@ public class SkipLevels implements Flushable {
* The "bottom" level is the direct pointer to a SkipSpan. * The "bottom" level is the direct pointer to a SkipSpan.
*/ */
// levels is almost final // levels is almost final
public SkipLevels[] levels; public SkipLevels<K, V>[] levels;
// bottom is final // bottom is final
public SkipSpan bottom; public SkipSpan<K, V> bottom;
private final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(BlockFile.class); private final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(BlockFile.class);
public SkipLevels newInstance(int levels, SkipSpan ss, SkipList sl) { return new SkipLevels(levels, ss); } public SkipLevels<K, V> newInstance(int levels, SkipSpan<K, V> ss, SkipList<K, V> sl) {
return new SkipLevels<K, V>(levels, ss);
}
public void killInstance() { } public void killInstance() { }
public void flush() { } public void flush() { }
@ -59,10 +62,10 @@ public class SkipLevels implements Flushable {
/* /*
* @throws IllegalArgumentException if size too big or too small * @throws IllegalArgumentException if size too big or too small
*/ */
public SkipLevels(int size, SkipSpan span) { public SkipLevels(int size, SkipSpan<K, V> span) {
if(size < 1 || size > MAX_SIZE) if(size < 1 || size > MAX_SIZE)
throw new IllegalArgumentException("Invalid Level Skip size"); throw new IllegalArgumentException("Invalid Level Skip size");
levels = new SkipLevels[size]; levels = (SkipLevels<K, V>[]) new SkipLevels[size];
bottom = span; bottom = span;
} }
@ -92,14 +95,14 @@ public class SkipLevels implements Flushable {
return buf.toString(); return buf.toString();
} }
public SkipSpan getEnd() { public SkipSpan<K, V> getEnd() {
for(int i=(levels.length - 1);i>=0;i--) { for(int i=(levels.length - 1);i>=0;i--) {
if(levels[i] != null) { return levels[i].getEnd(); } if(levels[i] != null) { return levels[i].getEnd(); }
} }
return bottom.getEnd(); return bottom.getEnd();
} }
public SkipSpan getSpan(int start, Comparable key, int[] search) { public SkipSpan<K, V> getSpan(int start, K key, int[] search) {
for(int i=Math.min(start, levels.length - 1);i>=0;i--) { for(int i=Math.min(start, levels.length - 1);i>=0;i--) {
if((levels[i] != null) && (levels[i].key().compareTo(key) <= 0)) { if((levels[i] != null) && (levels[i].key().compareTo(key) <= 0)) {
return levels[i].getSpan(i,key,search); return levels[i].getSpan(i,key,search);
@ -108,9 +111,9 @@ public class SkipLevels implements Flushable {
return bottom.getSpan(key, search); return bottom.getSpan(key, search);
} }
public Comparable key() { return bottom.firstKey(); } public K key() { return bottom.firstKey(); }
public Object get(int start, Comparable key) { public V get(int start, K key) {
for(int i=Math.min(start, levels.length - 1);i>=0;i--) { for(int i=Math.min(start, levels.length - 1);i>=0;i--) {
if((levels[i] != null) && (levels[i].key().compareTo(key) <= 0)) { if((levels[i] != null) && (levels[i].key().compareTo(key) <= 0)) {
return levels[i].get(i,key); return levels[i].get(i,key);
@ -126,16 +129,16 @@ public class SkipLevels implements Flushable {
* and the deleted SkipLevels is taller than this SkipLevels. * and the deleted SkipLevels is taller than this SkipLevels.
* rv is null if no object was removed. * rv is null if no object was removed.
*/ */
public Object[] remove(int start, Comparable key, SkipList sl) { public Object[] remove(int start, K key, SkipList<K, V> sl) {
Object[] res = null; Object[] res = null;
SkipLevels slvls = null; SkipLevels<K, V> slvls = null;
for(int i = Math.min(start, levels.length - 1); i >= 0; i--) { for(int i = Math.min(start, levels.length - 1); i >= 0; i--) {
if(levels[i] != null) { if(levels[i] != null) {
int cmp = levels[i].key().compareTo(key); int cmp = levels[i].key().compareTo(key);
if((cmp < 0) || ((i==0) && (cmp <= 0))) { if((cmp < 0) || ((i==0) && (cmp <= 0))) {
res = levels[i].remove(i, key, sl); res = levels[i].remove(i, key, sl);
if((res != null) && (res[1] != null)) { if((res != null) && (res[1] != null)) {
slvls = (SkipLevels) res[1]; slvls = (SkipLevels<K, V>) res[1];
if(levels.length >= slvls.levels.length) { if(levels.length >= slvls.levels.length) {
res[1] = null; res[1] = null;
} }
@ -159,7 +162,7 @@ public class SkipLevels implements Flushable {
// if the returned SkipSpan was already copied to us // if the returned SkipSpan was already copied to us
boolean isFirst = sl.first == bottom; boolean isFirst = sl.first == bottom;
if (isFirst && levels[0] != null) { if (isFirst && levels[0] != null) {
SkipSpan ssres = (SkipSpan)res[1]; SkipSpan<K, V> ssres = (SkipSpan<K, V>)res[1];
if (bottom.firstKey().equals(ssres.firstKey())) { if (bottom.firstKey().equals(ssres.firstKey())) {
// bottom copied the next span to itself // bottom copied the next span to itself
if (_log.shouldLog(Log.INFO)) { if (_log.shouldLog(Log.INFO)) {
@ -171,7 +174,7 @@ public class SkipLevels implements Flushable {
_log.info("FIXUP TIME"); _log.info("FIXUP TIME");
} }
SkipLevels replace = levels[0]; SkipLevels<K, V> replace = levels[0];
for (int i = 0; i < levels.length; i++) { for (int i = 0; i < levels.length; i++) {
if (levels[i] == null) if (levels[i] == null)
break; break;
@ -213,12 +216,12 @@ public class SkipLevels implements Flushable {
* and the new level is taller than our level; * and the new level is taller than our level;
* else null if it went in an existing level or the new level is our height or less. * else null if it went in an existing level or the new level is our height or less.
*/ */
public SkipLevels put(int start, Comparable key, Object val, SkipList sl) { public SkipLevels<K, V> put(int start, K key, V val, SkipList<K, V> sl) {
boolean modified = false; boolean modified = false;
for(int i = Math.min(start, levels.length - 1); i >= 0; i--) { for(int i = Math.min(start, levels.length - 1); i >= 0; i--) {
// is key equal to or after the start of the level? // is key equal to or after the start of the level?
if((levels[i] != null) && (levels[i].key().compareTo(key) <= 0)) { if((levels[i] != null) && (levels[i].key().compareTo(key) <= 0)) {
SkipLevels slvls = levels[i].put(i, key, val, sl); SkipLevels<K, V> slvls = levels[i].put(i, key, val, sl);
if(slvls != null) { if(slvls != null) {
for (int j = i + 1; j < Math.min(slvls.levels.length, levels.length); j++) { for (int j = i + 1; j < Math.min(slvls.levels.length, levels.length); j++) {
// he points to where we used to point // he points to where we used to point
@ -243,11 +246,11 @@ public class SkipLevels implements Flushable {
return null; return null;
} }
} }
SkipSpan ss = bottom.put(key,val,sl); SkipSpan<K, V> ss = bottom.put(key,val,sl);
if(ss!=null) { if(ss!=null) {
int height = sl.generateColHeight(); int height = sl.generateColHeight();
if(height != 0) { if(height != 0) {
SkipLevels slvls = this.newInstance(height, ss, sl); SkipLevels<K, V> slvls = this.newInstance(height, ss, sl);
for(int i=0;i<(Math.min(height,levels.length));i++) { for(int i=0;i<(Math.min(height,levels.length));i++) {
// he points to where we used to point // he points to where we used to point
// and we now point to him // and we now point to him
@ -267,6 +270,6 @@ public class SkipLevels implements Flushable {
} }
public boolean blvlck(boolean fix) { return false; } public boolean blvlck(boolean fix) { return false; }
public boolean blvlck(boolean fix, int width, SkipLevels[] prevLevels) { return false; } public boolean blvlck(boolean fix, int width, SkipLevels<K, V>[] prevLevels) { return false; }
} }

View File

@ -35,13 +35,13 @@ import net.i2p.util.RandomSource;
//import net.metanotion.io.block.BlockFile; //import net.metanotion.io.block.BlockFile;
public class SkipList implements Flushable { public class SkipList<K extends Comparable<? super K>, V> implements Flushable {
/** the probability of each next higher level */ /** the probability of each next higher level */
protected static final int P = 2; protected static final int P = 2;
private static final int MIN_SLOTS = 4; private static final int MIN_SLOTS = 4;
// these two are really final // these two are really final
protected SkipSpan first; protected SkipSpan<K, V> first;
protected SkipLevels stack; protected SkipLevels<K, V> stack;
// I2P mod // I2P mod
public static final Random rng = RandomSource.getInstance(); public static final Random rng = RandomSource.getInstance();
@ -57,8 +57,8 @@ public class SkipList implements Flushable {
public SkipList(int span) { public SkipList(int span) {
if(span < 1 || span > SkipSpan.MAX_SIZE) if(span < 1 || span > SkipSpan.MAX_SIZE)
throw new IllegalArgumentException("Invalid span size"); throw new IllegalArgumentException("Invalid span size");
first = new SkipSpan(span); first = new SkipSpan<K, V>(span);
stack = new SkipLevels(1, first); stack = new SkipLevels<K, V>(1, first);
//rng = new Random(System.currentTimeMillis()); //rng = new Random(System.currentTimeMillis());
} }
@ -95,14 +95,14 @@ public class SkipList implements Flushable {
return max; return max;
} }
public void put(Comparable key, Object val) { public void put(K key, V val) {
if(key == null) { throw new NullPointerException(); } if(key == null) { throw new NullPointerException(); }
if(val == null) { throw new NullPointerException(); } if(val == null) { throw new NullPointerException(); }
SkipLevels slvls = stack.put(stack.levels.length - 1, key, val, this); SkipLevels<K, V> slvls = stack.put(stack.levels.length - 1, key, val, this);
if(slvls != null) { if(slvls != null) {
// grow our stack // grow our stack
//BlockFile.log.info("Top level old hgt " + stack.levels.length + " new hgt " + slvls.levels.length); //BlockFile.log.info("Top level old hgt " + stack.levels.length + " new hgt " + slvls.levels.length);
SkipLevels[] levels = new SkipLevels[slvls.levels.length]; SkipLevels<K, V>[] levels = (SkipLevels<K, V>[]) new SkipLevels[slvls.levels.length];
for(int i=0;i < slvls.levels.length; i++) { for(int i=0;i < slvls.levels.length; i++) {
if(i < stack.levels.length) { if(i < stack.levels.length) {
levels[i] = stack.levels[i]; levels[i] = stack.levels[i];
@ -116,12 +116,12 @@ public class SkipList implements Flushable {
} }
} }
public Object remove(Comparable key) { public Object remove(K key) {
if(key == null) { throw new NullPointerException(); } if(key == null) { throw new NullPointerException(); }
Object[] res = stack.remove(stack.levels.length - 1, key, this); Object[] res = stack.remove(stack.levels.length - 1, key, this);
if(res != null) { if(res != null) {
if(res[1] != null) { if(res[1] != null) {
SkipLevels slvls = (SkipLevels) res[1]; SkipLevels<K, V> slvls = (SkipLevels<K, V>) res[1];
for(int i=0;i < slvls.levels.length; i++) { for(int i=0;i < slvls.levels.length; i++) {
if(stack.levels[i] == slvls) { if(stack.levels[i] == slvls) {
stack.levels[i] = slvls.levels[i]; stack.levels[i] = slvls.levels[i];
@ -154,26 +154,26 @@ public class SkipList implements Flushable {
System.out.println(first.print()); System.out.println(first.print());
} }
public Object get(Comparable key) { public V get(K key) {
if(key == null) { throw new NullPointerException(); } if(key == null) { throw new NullPointerException(); }
return stack.get(stack.levels.length - 1, key); return stack.get(stack.levels.length - 1, key);
} }
public SkipIterator iterator() { return new SkipIterator(first, 0); } public SkipIterator<K, V> iterator() { return new SkipIterator<K, V>(first, 0); }
public SkipIterator min() { return new SkipIterator(first, 0); } public SkipIterator<K, V> min() { return new SkipIterator<K, V>(first, 0); }
public SkipIterator max() { public SkipIterator<K, V> max() {
SkipSpan ss = stack.getEnd(); SkipSpan<K, V> ss = stack.getEnd();
return new SkipIterator(ss, ss.nKeys - 1); return new SkipIterator<K, V>(ss, ss.nKeys - 1);
} }
/** @return an iterator where nextKey() is the first one greater than or equal to 'key' */ /** @return an iterator where nextKey() is the first one greater than or equal to 'key' */
public SkipIterator find(Comparable key) { public SkipIterator<K, V> find(K key) {
int[] search = new int[1]; int[] search = new int[1];
SkipSpan ss = stack.getSpan(stack.levels.length - 1, key, search); SkipSpan<K, V> ss = stack.getSpan(stack.levels.length - 1, key, search);
if(search[0] < 0) { search[0] = -1 * (search[0] + 1); } if(search[0] < 0) { search[0] = -1 * (search[0] + 1); }
return new SkipIterator(ss, search[0]); return new SkipIterator<K, V>(ss, search[0]);
} }

View File

@ -32,16 +32,16 @@ import java.io.Flushable;
//import net.metanotion.io.block.BlockFile; //import net.metanotion.io.block.BlockFile;
public class SkipSpan implements Flushable { public class SkipSpan<K extends Comparable<? super K>, V> implements Flushable {
/** This is actually limited by BlockFile.spanSize which is much smaller */ /** This is actually limited by BlockFile.spanSize which is much smaller */
public static final int MAX_SIZE = 256; public static final int MAX_SIZE = 256;
public int nKeys = 0; public int nKeys = 0;
public Comparable[] keys; public K[] keys;
public Object[] vals; public V[] vals;
public SkipSpan next, prev; public SkipSpan<K, V> next, prev;
public SkipSpan newInstance(SkipList sl) { return new SkipSpan(keys.length); } public SkipSpan<K, V> newInstance(SkipList<K, V> sl) { return new SkipSpan<K, V>(keys.length); }
public void killInstance() { } public void killInstance() { }
public void flush() { } public void flush() { }
@ -53,8 +53,8 @@ public class SkipSpan implements Flushable {
public SkipSpan(int size) { public SkipSpan(int size) {
if(size < 1 || size > MAX_SIZE) if(size < 1 || size > MAX_SIZE)
throw new IllegalArgumentException("Invalid span size " + size); throw new IllegalArgumentException("Invalid span size " + size);
keys = new Comparable[size]; keys = (K[]) new Comparable[size];
vals = new Object[size]; vals = (V[]) new Object[size];
} }
/** dumps all the data from here to the end */ /** dumps all the data from here to the end */
@ -70,7 +70,7 @@ public class SkipSpan implements Flushable {
return buf.toString(); return buf.toString();
} }
private int binarySearch(Comparable key) { private int binarySearch(K key) {
int high = nKeys - 1; int high = nKeys - 1;
int low = 0; int low = 0;
int cur; int cur;
@ -89,12 +89,12 @@ public class SkipSpan implements Flushable {
return (-1 * (low + 1)); return (-1 * (low + 1));
} }
public SkipSpan getEnd() { public SkipSpan<K, V> getEnd() {
if(next == null) { return this; } if(next == null) { return this; }
return next.getEnd(); return next.getEnd();
} }
public SkipSpan getSpan(Comparable key, int[] search) { public SkipSpan<K, V> getSpan(K key, int[] search) {
if(nKeys == 0) { if(nKeys == 0) {
search[0] = -1; search[0] = -1;
return this; return this;
@ -111,7 +111,7 @@ public class SkipSpan implements Flushable {
return this; return this;
} }
public Object get(Comparable key) { public V get(K key) {
if(nKeys == 0) { return null; } if(nKeys == 0) { return null; }
if(keys[nKeys - 1].compareTo(key) < 0) { if(keys[nKeys - 1].compareTo(key) < 0) {
if(next == null) { return null; } if(next == null) { return null; }
@ -138,8 +138,8 @@ public class SkipSpan implements Flushable {
nKeys++; nKeys++;
} }
private void split(int loc, Comparable key, Object val, SkipList sl) { private void split(int loc, K key, V val, SkipList<K, V> sl) {
SkipSpan right = newInstance(sl); SkipSpan<K, V> right = newInstance(sl);
if(this.next != null) { this.next.prev = right; } if(this.next != null) { this.next.prev = right; }
right.next = this.next; right.next = this.next;
@ -175,7 +175,7 @@ public class SkipSpan implements Flushable {
/** /**
* @return the new span if it caused a split, else null if it went in this span * @return the new span if it caused a split, else null if it went in this span
*/ */
private SkipSpan insert(int loc, Comparable key, Object val, SkipList sl) { private SkipSpan<K, V> insert(int loc, K key, V val, SkipList<K, V> sl) {
sl.addItem(); sl.addItem();
if(nKeys == keys.length) { if(nKeys == keys.length) {
// split. // split.
@ -193,7 +193,7 @@ public class SkipSpan implements Flushable {
/** /**
* @return the new span if it caused a split, else null if it went in an existing span * @return the new span if it caused a split, else null if it went in an existing span
*/ */
public SkipSpan put(Comparable key, Object val, SkipList sl) { public SkipSpan<K, V> put(K key, V val, SkipList<K, V> sl) {
if(nKeys == 0) { if(nKeys == 0) {
sl.addItem(); sl.addItem();
keys[0] = key; keys[0] = key;
@ -246,7 +246,7 @@ public class SkipSpan implements Flushable {
* rv[1] is the deleted SkipSpan if the removed object was the last in the SkipSpan. * rv[1] is the deleted SkipSpan if the removed object was the last in the SkipSpan.
* rv is null if no object was removed. * rv is null if no object was removed.
*/ */
public Object[] remove(Comparable key, SkipList sl) { public Object[] remove(K key, SkipList<K, V> sl) {
if(nKeys == 0) { return null; } if(nKeys == 0) { return null; }
if(keys[nKeys - 1].compareTo(key) < 0) { if(keys[nKeys - 1].compareTo(key) < 0) {
if(next == null) { return null; } if(next == null) { return null; }
@ -270,7 +270,7 @@ public class SkipSpan implements Flushable {
nKeys = next.nKeys; nKeys = next.nKeys;
//BlockFile.log.error("Killing next span " + next + ") and copying to this span " + this + " in remove of " + key); //BlockFile.log.error("Killing next span " + next + ") and copying to this span " + this + " in remove of " + key);
// Make us point to next.next and him point back to us // Make us point to next.next and him point back to us
SkipSpan nn = next.next; SkipSpan<K, V> nn = next.next;
next.killInstance(); next.killInstance();
if (nn != null) { if (nn != null) {
nn.prev = this; nn.prev = this;
@ -311,7 +311,7 @@ public class SkipSpan implements Flushable {
} }
/** I2P */ /** I2P */
public Comparable firstKey() { public K firstKey() {
return keys[0]; return keys[0];
} }
} }