forked from I2P_Developers/i2p.i2p
Blockfile: Add generics, part 1
This commit is contained in:
@ -105,13 +105,13 @@ public class BlockfileNamingService extends DummyNamingService {
|
||||
private String _version = "0";
|
||||
private boolean _needsUpgrade;
|
||||
|
||||
private static final Serializer _infoSerializer = new PropertiesSerializer();
|
||||
private static final Serializer _stringSerializer = new UTF8StringBytes();
|
||||
private static final Serializer _destSerializerV1 = new DestEntrySerializer();
|
||||
private static final Serializer _destSerializerV4 = new DestEntrySerializerV4();
|
||||
private static final Serializer<Properties> _infoSerializer = new PropertiesSerializer();
|
||||
private static final Serializer<String> _stringSerializer = new UTF8StringBytes();
|
||||
private static final Serializer<DestEntry> _destSerializerV1 = new DestEntrySerializer();
|
||||
private static final Serializer<DestEntry> _destSerializerV4 = new DestEntrySerializerV4();
|
||||
// upgrade(), initExisting(), and initNew() will change this to _destSerializerV4
|
||||
private volatile Serializer _destSerializer = _destSerializerV1;
|
||||
private static final Serializer _hashIndexSerializer = new IntBytes();
|
||||
private volatile Serializer<DestEntry> _destSerializer = _destSerializerV1;
|
||||
private static final Serializer<Integer> _hashIndexSerializer = new IntBytes();
|
||||
|
||||
private static final String HOSTS_DB = "hostsdb.blockfile";
|
||||
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
|
||||
* 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 destination is fatal
|
||||
*/
|
||||
public byte[] getBytes(Object o) {
|
||||
DestEntry de = (DestEntry) o;
|
||||
public byte[] getBytes(DestEntry de) {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
|
||||
try {
|
||||
try {
|
||||
@ -1429,7 +1428,7 @@ public class BlockfileNamingService extends DummyNamingService {
|
||||
}
|
||||
|
||||
/** returns null on error */
|
||||
public Object construct(byte[] b) {
|
||||
public DestEntry construct(byte[] b) {
|
||||
DestEntry rv = new DestEntry();
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(b);
|
||||
try {
|
||||
@ -1452,10 +1451,9 @@ public class BlockfileNamingService extends DummyNamingService {
|
||||
* For multiple destinations per hostname
|
||||
* @since 0.9.26
|
||||
*/
|
||||
private static class DestEntrySerializerV4 implements Serializer {
|
||||
private static class DestEntrySerializerV4 implements Serializer<DestEntry> {
|
||||
|
||||
public byte[] getBytes(Object o) {
|
||||
DestEntry de = (DestEntry) o;
|
||||
public byte[] getBytes(DestEntry de) {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
|
||||
int sz = de.destList != null ? de.destList.size() : 1;
|
||||
try {
|
||||
@ -1487,7 +1485,7 @@ public class BlockfileNamingService extends DummyNamingService {
|
||||
}
|
||||
|
||||
/** returns null on error */
|
||||
public Object construct(byte[] b) {
|
||||
public DestEntry construct(byte[] b) {
|
||||
DestEntry rv = new DestEntry();
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(b);
|
||||
try {
|
||||
|
@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.metanotion.io;
|
||||
|
||||
public interface Serializer {
|
||||
public byte[] getBytes(Object o);
|
||||
public Object construct(byte[] b);
|
||||
public interface Serializer<T> {
|
||||
public byte[] getBytes(T o);
|
||||
public T construct(byte[] b);
|
||||
}
|
||||
|
@ -96,7 +96,7 @@ public class BlockFile implements Closeable {
|
||||
/** I2P was the file locked when we opened it? */
|
||||
private final boolean _wasMounted;
|
||||
|
||||
private final BSkipList metaIndex;
|
||||
private final BSkipList<String, Integer> metaIndex;
|
||||
private boolean _isClosed;
|
||||
/** cached list of free pages, only valid if freListStart > 0 */
|
||||
private FreeListBlock flb;
|
||||
@ -322,7 +322,7 @@ public class BlockFile implements Closeable {
|
||||
if (rai.canWrite())
|
||||
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
|
||||
*/
|
||||
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
|
||||
BSkipList bsl = openIndices.get(name);
|
||||
BSkipList<K, V> bsl = (BSkipList<K, V>) openIndices.get(name);
|
||||
if (bsl != null)
|
||||
return bsl;
|
||||
|
||||
Integer page = (Integer) metaIndex.get(name);
|
||||
Integer page = metaIndex.get(name);
|
||||
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()) {
|
||||
log.info("Checking skiplist " + name + " in blockfile " + file);
|
||||
if (bsl.bslck(true, false))
|
||||
@ -468,12 +468,12 @@ public class BlockFile implements Closeable {
|
||||
*
|
||||
* @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"); }
|
||||
int page = allocPage();
|
||||
metaIndex.put(name, Integer.valueOf(page));
|
||||
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);
|
||||
return bsl;
|
||||
}
|
||||
@ -516,24 +516,24 @@ public class BlockFile implements Closeable {
|
||||
* @throws IOException if it is open or on errors
|
||||
* @since 0.9.26
|
||||
*/
|
||||
public void reformatIndex(String name, Serializer oldKey, Serializer oldVal,
|
||||
Serializer newKey, Serializer newVal) throws IOException {
|
||||
public <K extends Comparable<? super K>, V> void reformatIndex(String name, Serializer<K> oldKey, Serializer<V> oldVal,
|
||||
Serializer<K> newKey, Serializer<V> newVal) throws IOException {
|
||||
if (openIndices.containsKey(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)
|
||||
return;
|
||||
long start = System.currentTimeMillis();
|
||||
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
|
||||
// SkipSpan layer but that's way too hard.
|
||||
final int loop = 32;
|
||||
List<Comparable> keys = new ArrayList<Comparable>(loop);
|
||||
List<Object> vals = new ArrayList<Object>(loop);
|
||||
List<K> keys = new ArrayList<K>(loop);
|
||||
List<V> vals = new ArrayList<V>(loop);
|
||||
while (true) {
|
||||
SkipIterator iter = old.iterator();
|
||||
SkipIterator<K, V> iter = old.iterator();
|
||||
for (int i = 0; iter.hasNext() && i < loop; i++) {
|
||||
keys.add(iter.nextKey());
|
||||
vals.add(iter.next());
|
||||
@ -555,7 +555,7 @@ public class BlockFile implements Closeable {
|
||||
delIndex(name);
|
||||
closeIndex(name);
|
||||
closeIndex(tmpName);
|
||||
Integer page = (Integer) metaIndex.get(tmpName);
|
||||
Integer page = metaIndex.get(tmpName);
|
||||
metaIndex.put(name, page);
|
||||
metaIndex.remove(tmpName);
|
||||
if (log.shouldWarn())
|
||||
@ -623,9 +623,15 @@ public class BlockFile implements Closeable {
|
||||
try {
|
||||
// This uses IdentityBytes, so the value class won't be right, but at least
|
||||
// it won't fail the out-of-order check
|
||||
Serializer keyser = slname.equals("%%__REVERSE__%%") ? new IntBytes() : new UTF8StringBytes();
|
||||
BSkipList bsl = getIndex(slname, keyser, new IdentityBytes());
|
||||
if (bsl == null) {
|
||||
boolean fail;
|
||||
if (slname.equals("%%__REVERSE__%%")) {
|
||||
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);
|
||||
continue;
|
||||
}
|
||||
|
@ -55,13 +55,13 @@ import net.i2p.util.Log;
|
||||
*
|
||||
* 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"
|
||||
static final int HEADER_LEN = 16;
|
||||
public final int levelPage;
|
||||
public final int spanPage;
|
||||
public final BlockFile bf;
|
||||
private final BSkipList bsl;
|
||||
private final BSkipList<K, V> bsl;
|
||||
private boolean isKilled;
|
||||
// the level pages, passed from the constructor to initializeLevels(),
|
||||
// NOT kept up to date
|
||||
@ -73,7 +73,7 @@ public class BSkipLevels extends SkipLevels {
|
||||
* after the constructor, unless it's a new empty
|
||||
* 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.bf = bf;
|
||||
this.bsl = bsl;
|
||||
@ -97,7 +97,7 @@ public class BSkipLevels extends SkipLevels {
|
||||
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))
|
||||
bf.log.debug("Reading New BSkipLevels with " + nonNull + " / " + maxLen + " valid levels page " + levelPage +
|
||||
" in skiplist " + bsl);
|
||||
@ -118,14 +118,14 @@ public class BSkipLevels extends SkipLevels {
|
||||
* @since 0.9.20
|
||||
*/
|
||||
public void initializeLevels() {
|
||||
List<BSkipLevels> toInit = new ArrayList<BSkipLevels>(32);
|
||||
List<BSkipLevels> nextInit = new ArrayList<BSkipLevels>(32);
|
||||
List<BSkipLevels<K, V>> toInit = new ArrayList<BSkipLevels<K, V>>(32);
|
||||
List<BSkipLevels<K, V>> nextInit = new ArrayList<BSkipLevels<K, V>>(32);
|
||||
initializeLevels(toInit);
|
||||
while (!toInit.isEmpty()) {
|
||||
for (BSkipLevels bsl : toInit) {
|
||||
for (BSkipLevels<K, V> bsl : toInit) {
|
||||
bsl.initializeLevels(nextInit);
|
||||
}
|
||||
List<BSkipLevels> tmp = toInit;
|
||||
List<BSkipLevels<K, V>> tmp = toInit;
|
||||
toInit = nextInit;
|
||||
nextInit = tmp;
|
||||
nextInit.clear();
|
||||
@ -139,7 +139,7 @@ public class BSkipLevels extends SkipLevels {
|
||||
* @param nextInit out parameter, next levels to initialize
|
||||
* @since 0.9.20
|
||||
*/
|
||||
private void initializeLevels(List<BSkipLevels> nextInit) {
|
||||
private void initializeLevels(List<BSkipLevels<K, V>> nextInit) {
|
||||
boolean fail = false;
|
||||
for(int i = 0; i < lps.length; i++) {
|
||||
int lp = lps[i];
|
||||
@ -147,7 +147,7 @@ public class BSkipLevels extends SkipLevels {
|
||||
levels[i] = bsl.levelHash.get(Integer.valueOf(lp));
|
||||
if(levels[i] == null) {
|
||||
try {
|
||||
BSkipLevels lev = new BSkipLevels(bf, lp, bsl);
|
||||
BSkipLevels<K, V> lev = new BSkipLevels<K, V>(bf, lp, bsl);
|
||||
levels[i] = lev;
|
||||
nextInit.add(lev);
|
||||
} catch (IOException ioe) {
|
||||
@ -158,8 +158,8 @@ public class BSkipLevels extends SkipLevels {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
Comparable ourKey = key();
|
||||
Comparable nextKey = levels[i].key();
|
||||
K ourKey = key();
|
||||
K nextKey = levels[i].key();
|
||||
if (ourKey != null && nextKey != null &&
|
||||
ourKey.compareTo(nextKey) >= 0) {
|
||||
bf.log.warn("Corrupt database, level out of order " + this +
|
||||
@ -215,9 +215,9 @@ public class BSkipLevels extends SkipLevels {
|
||||
break;
|
||||
}
|
||||
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++) {
|
||||
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); }
|
||||
}
|
||||
@ -236,15 +236,15 @@ public class BSkipLevels extends SkipLevels {
|
||||
}
|
||||
|
||||
@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 {
|
||||
BSkipSpan bss = (BSkipSpan) ss;
|
||||
BSkipList bsl = (BSkipList) sl;
|
||||
BSkipSpan<K, V> bss = (BSkipSpan<K, V>) ss;
|
||||
BSkipList<K, V> bsl = (BSkipList<K, V>) sl;
|
||||
int page = bf.allocPage();
|
||||
BSkipLevels.init(bf, page, bss.page, levels);
|
||||
if (bf.log.shouldLog(Log.DEBUG))
|
||||
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
|
||||
} catch (IOException ioe) { throw new RuntimeException("Error creating database page", ioe); }
|
||||
}
|
||||
@ -273,7 +273,7 @@ public class BSkipLevels extends SkipLevels {
|
||||
* @since 0.8.8
|
||||
*/
|
||||
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))
|
||||
bf.log.debug("Starting level search");
|
||||
getAllLevels(this, lvls);
|
||||
@ -285,15 +285,15 @@ public class BSkipLevels extends SkipLevels {
|
||||
}
|
||||
// traverse the levels, back-to-front
|
||||
boolean rv = false;
|
||||
SkipLevels after = null;
|
||||
for (SkipLevels lv : lvls) {
|
||||
SkipLevels<K, V> after = null;
|
||||
for (SkipLevels<K, V> lv : lvls) {
|
||||
boolean modified = false;
|
||||
if (bf.log.shouldLog(Log.DEBUG))
|
||||
bf.log.debug("Checking " + lv.print());
|
||||
if (after != null) {
|
||||
int min = Math.min(after.levels.length, lv.levels.length);
|
||||
for (int i = 0; i < min; i++) {
|
||||
SkipLevels cur = lv.levels[i];
|
||||
SkipLevels<K, V> cur = lv.levels[i];
|
||||
if (cur != after) {
|
||||
if (cur != null)
|
||||
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
|
||||
* @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))
|
||||
bf.log.debug("GAL " + l.print());
|
||||
// Do level 0 without recursion, on the assumption everything is findable
|
||||
// from the root
|
||||
SkipLevels cur = l;
|
||||
SkipLevels<K, V> cur = l;
|
||||
while (cur != null && lvlSet.add(cur)) {
|
||||
if (bf.log.shouldLog(Log.DEBUG))
|
||||
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,
|
||||
// i.e. there are no problems, this won't find anything
|
||||
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))
|
||||
getAllLevels(lv, lvlSet);
|
||||
}
|
||||
@ -358,10 +358,10 @@ public class BSkipLevels extends SkipLevels {
|
||||
* Sorts in REVERSE order.
|
||||
* @since 0.8.8
|
||||
*/
|
||||
private static class LevelComparator implements Comparator<SkipLevels>, Serializable {
|
||||
public int compare(SkipLevels l, SkipLevels r) {
|
||||
Comparable lk = l.key();
|
||||
Comparable rk = r.key();
|
||||
private static class LevelComparator<K extends Comparable<? super K>, V> implements Comparator<SkipLevels<K, V>>, Serializable {
|
||||
public int compare(SkipLevels<K, V> l, SkipLevels<K, V> r) {
|
||||
K lk = l.key();
|
||||
K rk = r.key();
|
||||
if (lk == null && rk == null)
|
||||
return 0;
|
||||
if (lk == null)
|
||||
@ -378,13 +378,13 @@ public class BSkipLevels extends SkipLevels {
|
||||
* This needs work.
|
||||
*/
|
||||
@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(" levels " + this.levels.length);
|
||||
bf.log.warn(" first key " + this.key());
|
||||
bf.log.warn(" spanPage " + this.spanPage);
|
||||
bf.log.warn(" levelPage " + this.levelPage);
|
||||
SkipLevels higher = null;
|
||||
SkipLevels<K, V> higher = null;
|
||||
for (int i = levels.length - 1; i >= 0; i--) {
|
||||
if (levels[i] != null) {
|
||||
bf.log.info(" level " + i + " -> " + levels[i].key() + " ");
|
||||
@ -418,7 +418,7 @@ public class BSkipLevels extends SkipLevels {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
prevLevels = new SkipLevels[levels.length];
|
||||
prevLevels = (SkipLevels<K, V>[]) new SkipLevels[levels.length];
|
||||
System.arraycopy(levels, 0, prevLevels, 0, levels.length);
|
||||
}
|
||||
if (levels[0] != null)
|
||||
|
@ -51,7 +51,7 @@ import net.i2p.util.Log;
|
||||
*
|
||||
* 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"
|
||||
public int firstSpanPage = 0;
|
||||
public int firstLevelPage = 0;
|
||||
@ -59,16 +59,16 @@ public class BSkipList extends SkipList implements Closeable {
|
||||
public final BlockFile bf;
|
||||
private boolean isClosed;
|
||||
|
||||
final HashMap<Integer, BSkipSpan> spanHash = new HashMap<Integer, BSkipSpan>();
|
||||
final HashMap<Integer, SkipLevels> levelHash = new HashMap<Integer, SkipLevels>();
|
||||
final HashMap<Integer, BSkipSpan<K, V>> spanHash = new HashMap<Integer, BSkipSpan<K, V>>();
|
||||
final HashMap<Integer, SkipLevels<K, V>> levelHash = new HashMap<Integer, SkipLevels<K, V>>();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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"); }
|
||||
|
||||
this.skipPage = skipPage;
|
||||
@ -89,10 +89,10 @@ public class BSkipList extends SkipList implements Closeable {
|
||||
|
||||
this.fileOnly = fileOnly;
|
||||
if (fileOnly)
|
||||
first = new IBSkipSpan(bf, this, firstSpanPage, key, val);
|
||||
first = new IBSkipSpan<K, V>(bf, this, firstSpanPage, key, val);
|
||||
else
|
||||
first = new BSkipSpan(bf, this, firstSpanPage, key, val);
|
||||
BSkipLevels bstack = new BSkipLevels(bf, firstLevelPage, this);
|
||||
first = new BSkipSpan<K, V>(bf, this, firstSpanPage, key, val);
|
||||
BSkipLevels<K, V> bstack = new BSkipLevels<K, V>(bf, firstLevelPage, this);
|
||||
bstack.initializeLevels();
|
||||
stack = bstack;
|
||||
int total = 0;
|
||||
@ -199,33 +199,33 @@ public class BSkipList extends SkipList implements Closeable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public SkipIterator iterator() {
|
||||
public SkipIterator<K, V> iterator() {
|
||||
if (!this.fileOnly)
|
||||
return super.iterator();
|
||||
return new IBSkipIterator(first, 0);
|
||||
return new IBSkipIterator<K, V>(first, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SkipIterator min() {
|
||||
public SkipIterator<K, V> min() {
|
||||
return iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SkipIterator max() {
|
||||
public SkipIterator<K, V> max() {
|
||||
if (!this.fileOnly)
|
||||
return super.max();
|
||||
SkipSpan ss = stack.getEnd();
|
||||
return new IBSkipIterator(ss, ss.nKeys - 1);
|
||||
SkipSpan<K, V> ss = stack.getEnd();
|
||||
return new IBSkipIterator<K, V>(ss, ss.nKeys - 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SkipIterator find(Comparable key) {
|
||||
public SkipIterator<K, V> find(K key) {
|
||||
if (!this.fileOnly)
|
||||
return super.find(key);
|
||||
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); }
|
||||
return new IBSkipIterator(ss, search[0]);
|
||||
return new IBSkipIterator<K, V>(ss, search[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -59,19 +59,19 @@ import net.i2p.util.Log;
|
||||
* next overflow page (unsigned int)
|
||||
*</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 HEADER_LEN = 20;
|
||||
public static final int CONT_HEADER_LEN = 8;
|
||||
protected final BlockFile bf;
|
||||
private final BSkipList bsl;
|
||||
private final BSkipList<K, V> bsl;
|
||||
protected int page;
|
||||
protected int overflowPage;
|
||||
|
||||
protected int prevPage;
|
||||
protected int nextPage = 0;
|
||||
protected Serializer keySer;
|
||||
protected Serializer valSer;
|
||||
protected Serializer<K> keySer;
|
||||
protected Serializer<V> valSer;
|
||||
|
||||
// I2P
|
||||
protected int spanSize;
|
||||
@ -88,11 +88,11 @@ public class BSkipSpan extends SkipSpan {
|
||||
}
|
||||
|
||||
@Override
|
||||
public SkipSpan newInstance(SkipList sl) {
|
||||
public SkipSpan<K, V> newInstance(SkipList<K, V> sl) {
|
||||
try {
|
||||
int newPage = bf.allocPage();
|
||||
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); }
|
||||
}
|
||||
|
||||
@ -237,7 +237,8 @@ public class BSkipSpan extends SkipSpan {
|
||||
//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);
|
||||
bss.loadData();
|
||||
}
|
||||
@ -246,7 +247,8 @@ public class BSkipSpan extends SkipSpan {
|
||||
* I2P - first half of load()
|
||||
* 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)
|
||||
throw new IOException("Already killed!! " + bss);
|
||||
bss.page = spanPage;
|
||||
@ -288,8 +290,8 @@ public class BSkipSpan extends SkipSpan {
|
||||
protected void loadData(boolean flushOnError) throws IOException {
|
||||
if (isKilled)
|
||||
throw new IOException("Already killed!! " + this);
|
||||
this.keys = new Comparable[this.spanSize];
|
||||
this.vals = new Object[this.spanSize];
|
||||
this.keys = (K[]) new Comparable[this.spanSize];
|
||||
this.vals = (V[]) new Object[this.spanSize];
|
||||
|
||||
int ksz, vsz;
|
||||
int curPage = this.page;
|
||||
@ -327,7 +329,7 @@ public class BSkipSpan extends SkipSpan {
|
||||
break;
|
||||
}
|
||||
// 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);
|
||||
// Drop bad entry without throwing exception
|
||||
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.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.bsl = bsl;
|
||||
BSkipSpan.load(this, bf, bsl, spanPage, key, val);
|
||||
this.next = null;
|
||||
this.prev = null;
|
||||
|
||||
BSkipSpan bss = this;
|
||||
BSkipSpan<K, V> bss = this;
|
||||
// findbugs ok (set in load() above)
|
||||
int np = nextPage;
|
||||
while(np != 0) {
|
||||
BSkipSpan temp = bsl.spanHash.get(Integer.valueOf(np));
|
||||
BSkipSpan<K, V> temp = bsl.spanHash.get(Integer.valueOf(np));
|
||||
if(temp != null) {
|
||||
bss.next = temp;
|
||||
break;
|
||||
}
|
||||
bss.next = new BSkipSpan(bf, bsl);
|
||||
bss.next = new BSkipSpan<K, V>(bf, bsl);
|
||||
bss.next.next = null;
|
||||
bss.next.prev = bss;
|
||||
bss = (BSkipSpan) bss.next;
|
||||
bss = (BSkipSpan<K, V>) bss.next;
|
||||
|
||||
BSkipSpan.load(bss, bf, bsl, np, key, val);
|
||||
np = bss.nextPage;
|
||||
@ -411,15 +413,15 @@ public class BSkipSpan extends SkipSpan {
|
||||
bss = this;
|
||||
np = prevPage;
|
||||
while(np != 0) {
|
||||
BSkipSpan temp = bsl.spanHash.get(Integer.valueOf(np));
|
||||
BSkipSpan<K, V> temp = bsl.spanHash.get(Integer.valueOf(np));
|
||||
if(temp != null) {
|
||||
bss.prev = temp;
|
||||
break;
|
||||
}
|
||||
bss.prev = new BSkipSpan(bf, bsl);
|
||||
bss.prev = new BSkipSpan<K, V>(bf, bsl);
|
||||
bss.prev.next = bss;
|
||||
bss.prev.prev = null;
|
||||
bss = (BSkipSpan) bss.prev;
|
||||
bss = (BSkipSpan<K, V>) bss.prev;
|
||||
|
||||
BSkipSpan.load(bss, bf, bsl, np, key, val);
|
||||
np = bss.prevPage;
|
||||
|
@ -41,9 +41,9 @@ import net.metanotion.util.skiplist.SkipSpan;
|
||||
If the caller does not iterate all the way through, the last span
|
||||
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);
|
||||
}
|
||||
|
||||
@ -53,8 +53,8 @@ public class IBSkipIterator extends SkipIterator {
|
||||
* @throws RuntimeException on IOE
|
||||
*/
|
||||
@Override
|
||||
public Object next() {
|
||||
Object o;
|
||||
public V next() {
|
||||
V o;
|
||||
if(index < ss.nKeys) {
|
||||
if (ss.vals == null) {
|
||||
try {
|
||||
@ -90,7 +90,7 @@ public class IBSkipIterator extends SkipIterator {
|
||||
* @throws RuntimeException on IOE
|
||||
*/
|
||||
@Override
|
||||
public Comparable nextKey() {
|
||||
public K nextKey() {
|
||||
if(index < ss.nKeys) {
|
||||
if (ss.keys == null) {
|
||||
try {
|
||||
@ -110,7 +110,7 @@ public class IBSkipIterator extends SkipIterator {
|
||||
* @throws RuntimeException on IOE
|
||||
*/
|
||||
@Override
|
||||
public Object previous() {
|
||||
public V previous() {
|
||||
if(index > 0) {
|
||||
index--;
|
||||
} else if(ss.prev != null) {
|
||||
|
@ -54,21 +54,21 @@ import net.i2p.util.Log;
|
||||
*
|
||||
* @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
|
||||
public SkipSpan newInstance(SkipList sl) {
|
||||
public SkipSpan<K, V> newInstance(SkipList<K, V> sl) {
|
||||
if (bf.log.shouldLog(Log.DEBUG))
|
||||
bf.log.debug("Splitting page " + this.page + " containing " + this.nKeys + '/' + this.spanSize);
|
||||
try {
|
||||
int newPage = bf.allocPage();
|
||||
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
|
||||
rv.keys = new Comparable[bf.spanSize];
|
||||
rv.vals = new Object[bf.spanSize];
|
||||
rv.keys = (K[]) new Comparable[bf.spanSize];
|
||||
rv.vals = (V[]) new Object[bf.spanSize];
|
||||
return rv;
|
||||
} catch (IOException ioe) { throw new RuntimeException("Error creating database page", ioe); }
|
||||
}
|
||||
@ -125,7 +125,7 @@ public class IBSkipSpan extends BSkipSpan {
|
||||
pageCounter[0] +=4;
|
||||
byte[] k = new byte[ksz];
|
||||
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) {
|
||||
bf.log.error("Null deserialized first key in page " + curPage);
|
||||
repair(1);
|
||||
@ -160,7 +160,7 @@ public class IBSkipSpan extends BSkipSpan {
|
||||
/**
|
||||
* 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();
|
||||
int curPage = this.page;
|
||||
int[] curNextPage = new int[1];
|
||||
@ -194,7 +194,7 @@ public class IBSkipSpan extends BSkipSpan {
|
||||
break;
|
||||
}
|
||||
//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) {
|
||||
// skip the value and keep going
|
||||
curPage = this.bf.skipMultiPageBytes(vsz, curPage, pageCounter, curNextPage);
|
||||
@ -213,7 +213,7 @@ public class IBSkipSpan extends BSkipSpan {
|
||||
lostEntries(i, curPage);
|
||||
break;
|
||||
}
|
||||
Object rv = this.valSer.construct(v);
|
||||
V rv = this.valSer.construct(v);
|
||||
if (rv == null) {
|
||||
bf.log.error("Null deserialized value in entry " + i + " page " + curPage +
|
||||
" 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);
|
||||
}
|
||||
|
||||
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);
|
||||
if (bf.log.shouldLog(Log.DEBUG))
|
||||
bf.log.debug("New ibss page " + spanPage);
|
||||
@ -265,24 +265,24 @@ public class IBSkipSpan extends BSkipSpan {
|
||||
this.next = null;
|
||||
this.prev = null;
|
||||
|
||||
IBSkipSpan bss = this;
|
||||
IBSkipSpan temp;
|
||||
IBSkipSpan<K, V> bss = this;
|
||||
IBSkipSpan<K, V> temp;
|
||||
int np = nextPage;
|
||||
while(np != 0) {
|
||||
temp = (IBSkipSpan) bsl.spanHash.get(Integer.valueOf(np));
|
||||
temp = (IBSkipSpan<K, V>) bsl.spanHash.get(Integer.valueOf(np));
|
||||
if(temp != null) {
|
||||
bss.next = temp;
|
||||
break;
|
||||
}
|
||||
bss.next = new IBSkipSpan(bf, bsl);
|
||||
bss.next = new IBSkipSpan<K, V>(bf, bsl);
|
||||
bss.next.next = null;
|
||||
bss.next.prev = bss;
|
||||
Comparable previousFirstKey = bss.firstKey;
|
||||
bss = (IBSkipSpan) bss.next;
|
||||
K previousFirstKey = bss.firstKey;
|
||||
bss = (IBSkipSpan<K, V>) bss.next;
|
||||
|
||||
BSkipSpan.loadInit(bss, bf, bsl, np, key, val);
|
||||
bss.loadFirstKey();
|
||||
Comparable nextFirstKey = bss.firstKey;
|
||||
K nextFirstKey = bss.firstKey;
|
||||
if (previousFirstKey == null || nextFirstKey == null ||
|
||||
previousFirstKey.compareTo(nextFirstKey) >= 0) {
|
||||
// TODO remove, but if we are at the bottom of a level
|
||||
@ -299,20 +299,20 @@ public class IBSkipSpan extends BSkipSpan {
|
||||
bss = this;
|
||||
np = prevPage;
|
||||
while(np != 0) {
|
||||
temp = (IBSkipSpan) bsl.spanHash.get(Integer.valueOf(np));
|
||||
temp = (IBSkipSpan<K, V>) bsl.spanHash.get(Integer.valueOf(np));
|
||||
if(temp != null) {
|
||||
bss.prev = temp;
|
||||
break;
|
||||
}
|
||||
bss.prev = new IBSkipSpan(bf, bsl);
|
||||
bss.prev = new IBSkipSpan<K, V>(bf, bsl);
|
||||
bss.prev.next = bss;
|
||||
bss.prev.prev = null;
|
||||
Comparable nextFirstKey = bss.firstKey;
|
||||
bss = (IBSkipSpan) bss.prev;
|
||||
K nextFirstKey = bss.firstKey;
|
||||
bss = (IBSkipSpan<K, V>) bss.prev;
|
||||
|
||||
BSkipSpan.loadInit(bss, bf, bsl, np, key, val);
|
||||
bss.loadFirstKey();
|
||||
Comparable previousFirstKey = bss.firstKey;
|
||||
K previousFirstKey = bss.firstKey;
|
||||
if (previousFirstKey == null || nextFirstKey == null ||
|
||||
previousFirstKey.compareTo(nextFirstKey) >= 0) {
|
||||
// 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
|
||||
*/
|
||||
@Override
|
||||
public Comparable firstKey() {
|
||||
public K firstKey() {
|
||||
return this.firstKey;
|
||||
}
|
||||
|
||||
@ -339,13 +339,13 @@ public class IBSkipSpan extends BSkipSpan {
|
||||
* This is called only via SkipList.find()
|
||||
*/
|
||||
@Override
|
||||
public SkipSpan getSpan(Comparable key, int[] search) {
|
||||
public SkipSpan<K, V> getSpan(K key, int[] search) {
|
||||
try {
|
||||
seekAndLoadData();
|
||||
} catch (IOException 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.vals = null;
|
||||
return rv;
|
||||
@ -355,7 +355,7 @@ public class IBSkipSpan extends BSkipSpan {
|
||||
* Linear search if in file, Binary search if in memory
|
||||
*/
|
||||
@Override
|
||||
public Object get(Comparable key) {
|
||||
public V get(K key) {
|
||||
try {
|
||||
if (nKeys == 0) { return null; }
|
||||
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.
|
||||
*/
|
||||
@Override
|
||||
public SkipSpan put(Comparable key, Object val, SkipList sl) {
|
||||
public SkipSpan<K, V> put(K key, V val, SkipList<K, V> sl) {
|
||||
try {
|
||||
seekAndLoadData();
|
||||
} catch (IOException 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
|
||||
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.
|
||||
*/
|
||||
@Override
|
||||
public Object[] remove(Comparable key, SkipList sl) {
|
||||
public Object[] remove(K key, SkipList<K, V> sl) {
|
||||
if (bf.log.shouldLog(Log.DEBUG))
|
||||
bf.log.debug("Remove " + key + " in " + this);
|
||||
if (nKeys <= 0)
|
||||
|
@ -35,11 +35,11 @@ import net.metanotion.io.Serializer;
|
||||
* Will never return null.
|
||||
* Added by I2P.
|
||||
*/
|
||||
public class IdentityBytes implements Serializer {
|
||||
public class IdentityBytes implements Serializer<byte[]> {
|
||||
|
||||
/** @return byte[] */
|
||||
public byte[] getBytes(Object o) { return (byte[])o; }
|
||||
public byte[] getBytes(byte[] o) { return o; }
|
||||
|
||||
/** @return b */
|
||||
public Object construct(byte[] b) { return b; }
|
||||
public byte[] construct(byte[] b) { return b; }
|
||||
}
|
||||
|
@ -30,10 +30,10 @@ package net.metanotion.io.data;
|
||||
|
||||
import net.metanotion.io.Serializer;
|
||||
|
||||
public class IntBytes implements Serializer {
|
||||
public byte[] getBytes(Object o) {
|
||||
public class IntBytes implements Serializer<Integer> {
|
||||
public byte[] getBytes(Integer o) {
|
||||
byte[] b = new byte[4];
|
||||
int v = ((Integer) o).intValue();
|
||||
int v = o.intValue();
|
||||
b[0] = (byte)(0xff & (v >> 24));
|
||||
b[1] = (byte)(0xff & (v >> 16));
|
||||
b[2] = (byte)(0xff & (v >> 8));
|
||||
@ -41,7 +41,7 @@ public class IntBytes implements Serializer {
|
||||
return b;
|
||||
}
|
||||
|
||||
public Object construct(byte[] b) {
|
||||
public Integer construct(byte[] b) {
|
||||
int v = (((b[0] & 0xff) << 24) |
|
||||
((b[1] & 0xff) << 16) |
|
||||
((b[2] & 0xff) << 8) |
|
||||
|
@ -30,10 +30,10 @@ package net.metanotion.io.data;
|
||||
|
||||
import net.metanotion.io.Serializer;
|
||||
|
||||
public class LongBytes implements Serializer {
|
||||
public byte[] getBytes(Object o) {
|
||||
public class LongBytes implements Serializer<Long> {
|
||||
public byte[] getBytes(Long o) {
|
||||
byte[] b = new byte[8];
|
||||
long v = ((Long) o).longValue();
|
||||
long v = o.longValue();
|
||||
b[0] = (byte)(0xff & (v >> 56));
|
||||
b[1] = (byte)(0xff & (v >> 48));
|
||||
b[2] = (byte)(0xff & (v >> 40));
|
||||
@ -45,7 +45,7 @@ public class LongBytes implements Serializer {
|
||||
return b;
|
||||
}
|
||||
|
||||
public Object construct(byte[] b) {
|
||||
public Long construct(byte[] b) {
|
||||
long v =(((long)(b[0] & 0xff) << 56) |
|
||||
((long)(b[1] & 0xff) << 48) |
|
||||
((long)(b[2] & 0xff) << 40) |
|
||||
|
@ -30,7 +30,7 @@ package net.metanotion.io.data;
|
||||
|
||||
import net.metanotion.io.Serializer;
|
||||
|
||||
public class NullBytes implements Serializer {
|
||||
public class NullBytes implements Serializer<Object> {
|
||||
public byte[] getBytes(Object o) { return null; }
|
||||
public Object construct(byte[] b) { return null; }
|
||||
}
|
||||
|
@ -32,14 +32,14 @@ import java.io.UnsupportedEncodingException;
|
||||
|
||||
import net.metanotion.io.Serializer;
|
||||
|
||||
public class StringBytes implements Serializer {
|
||||
public byte[] getBytes(Object o) {
|
||||
public class StringBytes implements Serializer<String> {
|
||||
public byte[] getBytes(String o) {
|
||||
try {
|
||||
return ((String) o).getBytes("US-ASCII");
|
||||
return o.getBytes("US-ASCII");
|
||||
} catch (UnsupportedEncodingException uee) { throw new Error("Unsupported Encoding"); }
|
||||
}
|
||||
|
||||
public Object construct(byte[] b) {
|
||||
public String construct(byte[] b) {
|
||||
try {
|
||||
return new String(b, "US-ASCII");
|
||||
} catch (UnsupportedEncodingException uee) { throw new Error("Unsupported Encoding"); }
|
||||
|
@ -35,14 +35,14 @@ import net.metanotion.io.Serializer;
|
||||
/**
|
||||
* Added by I2P
|
||||
*/
|
||||
public class UTF8StringBytes implements Serializer {
|
||||
public byte[] getBytes(Object o) {
|
||||
public class UTF8StringBytes implements Serializer<String> {
|
||||
public byte[] getBytes(String o) {
|
||||
try {
|
||||
return ((String) o).getBytes("UTF-8");
|
||||
return o.getBytes("UTF-8");
|
||||
} catch (UnsupportedEncodingException uee) { throw new Error("Unsupported Encoding"); }
|
||||
}
|
||||
|
||||
public Object construct(byte[] b) {
|
||||
public String construct(byte[] b) {
|
||||
try {
|
||||
return new String(b, "UTF-8");
|
||||
} catch (UnsupportedEncodingException uee) { throw new Error("Unsupported Encoding"); }
|
||||
|
@ -39,12 +39,13 @@ import java.util.NoSuchElementException;
|
||||
To be clear, this is an iterator through the values.
|
||||
To get the key, call nextKey() BEFORE calling next().
|
||||
*/
|
||||
public class SkipIterator implements ListIterator {
|
||||
protected SkipSpan ss;
|
||||
public class SkipIterator<K extends Comparable<? super K>, V> implements ListIterator<V> {
|
||||
protected SkipSpan<K, V> ss;
|
||||
protected int index;
|
||||
|
||||
protected SkipIterator() { }
|
||||
public SkipIterator(SkipSpan ss, int index) {
|
||||
|
||||
public SkipIterator(SkipSpan<K, V> ss, int index) {
|
||||
if(ss==null) { throw new NullPointerException(); }
|
||||
this.ss = ss;
|
||||
this.index = index;
|
||||
@ -59,8 +60,8 @@ public class SkipIterator implements ListIterator {
|
||||
* @return the next value, and advances the index
|
||||
* @throws NoSuchElementException
|
||||
*/
|
||||
public Object next() {
|
||||
Object o;
|
||||
public V next() {
|
||||
V o;
|
||||
if(index < ss.nKeys) {
|
||||
o = ss.vals[index];
|
||||
} 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()
|
||||
* @throws NoSuchElementException
|
||||
*/
|
||||
public Comparable nextKey() {
|
||||
public K nextKey() {
|
||||
if(index < ss.nKeys) { return ss.keys[index]; }
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
@ -98,7 +99,7 @@ public class SkipIterator implements ListIterator {
|
||||
* @return the previous value, and decrements the index
|
||||
* @throws NoSuchElementException
|
||||
*/
|
||||
public Object previous() {
|
||||
public V previous() {
|
||||
if(index > 0) {
|
||||
index--;
|
||||
} else if(ss.prev != null) {
|
||||
@ -111,9 +112,9 @@ public class SkipIterator implements ListIterator {
|
||||
|
||||
|
||||
// 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 set(Object o) { throw new UnsupportedOperationException(); }
|
||||
public void set(V o) { throw new UnsupportedOperationException(); }
|
||||
public int nextIndex() { throw new UnsupportedOperationException(); }
|
||||
public int previousIndex() { throw new UnsupportedOperationException(); }
|
||||
|
||||
|
@ -35,7 +35,7 @@ import net.metanotion.io.block.BlockFile;
|
||||
import net.i2p.I2PAppContext;
|
||||
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 */
|
||||
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.
|
||||
*/
|
||||
// levels is almost final
|
||||
public SkipLevels[] levels;
|
||||
public SkipLevels<K, V>[] levels;
|
||||
// bottom is final
|
||||
public SkipSpan bottom;
|
||||
public SkipSpan<K, V> bottom;
|
||||
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 flush() { }
|
||||
|
||||
@ -59,10 +62,10 @@ public class SkipLevels implements Flushable {
|
||||
/*
|
||||
* @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)
|
||||
throw new IllegalArgumentException("Invalid Level Skip size");
|
||||
levels = new SkipLevels[size];
|
||||
levels = (SkipLevels<K, V>[]) new SkipLevels[size];
|
||||
bottom = span;
|
||||
}
|
||||
|
||||
@ -92,14 +95,14 @@ public class SkipLevels implements Flushable {
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public SkipSpan getEnd() {
|
||||
public SkipSpan<K, V> getEnd() {
|
||||
for(int i=(levels.length - 1);i>=0;i--) {
|
||||
if(levels[i] != null) { return levels[i].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--) {
|
||||
if((levels[i] != null) && (levels[i].key().compareTo(key) <= 0)) {
|
||||
return levels[i].getSpan(i,key,search);
|
||||
@ -108,9 +111,9 @@ public class SkipLevels implements Flushable {
|
||||
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--) {
|
||||
if((levels[i] != null) && (levels[i].key().compareTo(key) <= 0)) {
|
||||
return levels[i].get(i,key);
|
||||
@ -126,16 +129,16 @@ public class SkipLevels implements Flushable {
|
||||
* and the deleted SkipLevels is taller than this SkipLevels.
|
||||
* 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;
|
||||
SkipLevels slvls = null;
|
||||
SkipLevels<K, V> slvls = null;
|
||||
for(int i = Math.min(start, levels.length - 1); i >= 0; i--) {
|
||||
if(levels[i] != null) {
|
||||
int cmp = levels[i].key().compareTo(key);
|
||||
if((cmp < 0) || ((i==0) && (cmp <= 0))) {
|
||||
res = levels[i].remove(i, key, sl);
|
||||
if((res != null) && (res[1] != null)) {
|
||||
slvls = (SkipLevels) res[1];
|
||||
slvls = (SkipLevels<K, V>) res[1];
|
||||
if(levels.length >= slvls.levels.length) {
|
||||
res[1] = null;
|
||||
}
|
||||
@ -159,7 +162,7 @@ public class SkipLevels implements Flushable {
|
||||
// if the returned SkipSpan was already copied to us
|
||||
boolean isFirst = sl.first == bottom;
|
||||
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())) {
|
||||
// bottom copied the next span to itself
|
||||
if (_log.shouldLog(Log.INFO)) {
|
||||
@ -171,7 +174,7 @@ public class SkipLevels implements Flushable {
|
||||
_log.info("FIXUP TIME");
|
||||
}
|
||||
|
||||
SkipLevels replace = levels[0];
|
||||
SkipLevels<K, V> replace = levels[0];
|
||||
for (int i = 0; i < levels.length; i++) {
|
||||
if (levels[i] == null)
|
||||
break;
|
||||
@ -213,12 +216,12 @@ public class SkipLevels implements Flushable {
|
||||
* 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.
|
||||
*/
|
||||
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;
|
||||
for(int i = Math.min(start, levels.length - 1); i >= 0; i--) {
|
||||
// is key equal to or after the start of the level?
|
||||
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) {
|
||||
for (int j = i + 1; j < Math.min(slvls.levels.length, levels.length); j++) {
|
||||
// he points to where we used to point
|
||||
@ -243,11 +246,11 @@ public class SkipLevels implements Flushable {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
SkipSpan ss = bottom.put(key,val,sl);
|
||||
SkipSpan<K, V> ss = bottom.put(key,val,sl);
|
||||
if(ss!=null) {
|
||||
int height = sl.generateColHeight();
|
||||
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++) {
|
||||
// he points to where we used to point
|
||||
// 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, int width, SkipLevels[] prevLevels) { return false; }
|
||||
public boolean blvlck(boolean fix, int width, SkipLevels<K, V>[] prevLevels) { return false; }
|
||||
}
|
||||
|
||||
|
@ -35,13 +35,13 @@ import net.i2p.util.RandomSource;
|
||||
|
||||
//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 */
|
||||
protected static final int P = 2;
|
||||
private static final int MIN_SLOTS = 4;
|
||||
// these two are really final
|
||||
protected SkipSpan first;
|
||||
protected SkipLevels stack;
|
||||
protected SkipSpan<K, V> first;
|
||||
protected SkipLevels<K, V> stack;
|
||||
// I2P mod
|
||||
public static final Random rng = RandomSource.getInstance();
|
||||
|
||||
@ -57,8 +57,8 @@ public class SkipList implements Flushable {
|
||||
public SkipList(int span) {
|
||||
if(span < 1 || span > SkipSpan.MAX_SIZE)
|
||||
throw new IllegalArgumentException("Invalid span size");
|
||||
first = new SkipSpan(span);
|
||||
stack = new SkipLevels(1, first);
|
||||
first = new SkipSpan<K, V>(span);
|
||||
stack = new SkipLevels<K, V>(1, first);
|
||||
//rng = new Random(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
@ -95,14 +95,14 @@ public class SkipList implements Flushable {
|
||||
return max;
|
||||
}
|
||||
|
||||
public void put(Comparable key, Object val) {
|
||||
public void put(K key, V val) {
|
||||
if(key == 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) {
|
||||
// grow our stack
|
||||
//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++) {
|
||||
if(i < stack.levels.length) {
|
||||
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(); }
|
||||
Object[] res = stack.remove(stack.levels.length - 1, key, this);
|
||||
if(res != 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++) {
|
||||
if(stack.levels[i] == slvls) {
|
||||
stack.levels[i] = slvls.levels[i];
|
||||
@ -154,26 +154,26 @@ public class SkipList implements Flushable {
|
||||
System.out.println(first.print());
|
||||
}
|
||||
|
||||
public Object get(Comparable key) {
|
||||
public V get(K key) {
|
||||
if(key == null) { throw new NullPointerException(); }
|
||||
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() {
|
||||
SkipSpan ss = stack.getEnd();
|
||||
return new SkipIterator(ss, ss.nKeys - 1);
|
||||
public SkipIterator<K, V> max() {
|
||||
SkipSpan<K, V> ss = stack.getEnd();
|
||||
return new SkipIterator<K, V>(ss, ss.nKeys - 1);
|
||||
}
|
||||
|
||||
/** @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];
|
||||
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); }
|
||||
return new SkipIterator(ss, search[0]);
|
||||
return new SkipIterator<K, V>(ss, search[0]);
|
||||
}
|
||||
|
||||
|
||||
|
@ -32,16 +32,16 @@ import java.io.Flushable;
|
||||
|
||||
//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 */
|
||||
public static final int MAX_SIZE = 256;
|
||||
|
||||
public int nKeys = 0;
|
||||
public Comparable[] keys;
|
||||
public Object[] vals;
|
||||
public SkipSpan next, prev;
|
||||
public K[] keys;
|
||||
public V[] vals;
|
||||
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 flush() { }
|
||||
|
||||
@ -53,8 +53,8 @@ public class SkipSpan implements Flushable {
|
||||
public SkipSpan(int size) {
|
||||
if(size < 1 || size > MAX_SIZE)
|
||||
throw new IllegalArgumentException("Invalid span size " + size);
|
||||
keys = new Comparable[size];
|
||||
vals = new Object[size];
|
||||
keys = (K[]) new Comparable[size];
|
||||
vals = (V[]) new Object[size];
|
||||
}
|
||||
|
||||
/** dumps all the data from here to the end */
|
||||
@ -70,7 +70,7 @@ public class SkipSpan implements Flushable {
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
private int binarySearch(Comparable key) {
|
||||
private int binarySearch(K key) {
|
||||
int high = nKeys - 1;
|
||||
int low = 0;
|
||||
int cur;
|
||||
@ -89,12 +89,12 @@ public class SkipSpan implements Flushable {
|
||||
return (-1 * (low + 1));
|
||||
}
|
||||
|
||||
public SkipSpan getEnd() {
|
||||
public SkipSpan<K, V> getEnd() {
|
||||
if(next == null) { return this; }
|
||||
return next.getEnd();
|
||||
}
|
||||
|
||||
public SkipSpan getSpan(Comparable key, int[] search) {
|
||||
public SkipSpan<K, V> getSpan(K key, int[] search) {
|
||||
if(nKeys == 0) {
|
||||
search[0] = -1;
|
||||
return this;
|
||||
@ -111,7 +111,7 @@ public class SkipSpan implements Flushable {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Object get(Comparable key) {
|
||||
public V get(K key) {
|
||||
if(nKeys == 0) { return null; }
|
||||
if(keys[nKeys - 1].compareTo(key) < 0) {
|
||||
if(next == null) { return null; }
|
||||
@ -138,8 +138,8 @@ public class SkipSpan implements Flushable {
|
||||
nKeys++;
|
||||
}
|
||||
|
||||
private void split(int loc, Comparable key, Object val, SkipList sl) {
|
||||
SkipSpan right = newInstance(sl);
|
||||
private void split(int loc, K key, V val, SkipList<K, V> sl) {
|
||||
SkipSpan<K, V> right = newInstance(sl);
|
||||
|
||||
if(this.next != null) { this.next.prev = right; }
|
||||
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
|
||||
*/
|
||||
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();
|
||||
if(nKeys == keys.length) {
|
||||
// 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
|
||||
*/
|
||||
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) {
|
||||
sl.addItem();
|
||||
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 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(keys[nKeys - 1].compareTo(key) < 0) {
|
||||
if(next == null) { return null; }
|
||||
@ -270,7 +270,7 @@ public class SkipSpan implements Flushable {
|
||||
nKeys = next.nKeys;
|
||||
//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
|
||||
SkipSpan nn = next.next;
|
||||
SkipSpan<K, V> nn = next.next;
|
||||
next.killInstance();
|
||||
if (nn != null) {
|
||||
nn.prev = this;
|
||||
@ -311,7 +311,7 @@ public class SkipSpan implements Flushable {
|
||||
}
|
||||
|
||||
/** I2P */
|
||||
public Comparable firstKey() {
|
||||
public K firstKey() {
|
||||
return keys[0];
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user