package com.limegroup.gnutella.routing;
import java.util.Iterator;
/**
* A delegating QRTTableStorage that switches between
* SparseSetStorage and BitSetStorage implementation depending
* on the number of entries.
*/
class DynamicQRTStorage implements QRTTableStorage {
/**
* A treshold at which a 128kbit BitSetStorage will use less memory
* than a SparseSetStorage. Determined experimentally.
*/
private final float TRESHOLD = 2.5f;
/**
* The current storage we use.
*/
private QRTTableStorage storage;
DynamicQRTStorage(int length) {
this(new SparseSetStorage(length));
}
private DynamicQRTStorage(QRTTableStorage storage) {
this.storage = storage;
}
public void clear(int hash) {
storage.clear(hash);
}
public void compact() {
changeStorage();
storage.compact();
}
/**
* changes the storage implementation if necessary.
*/
private void changeStorage() {
if (storage.getPercentFull() > TRESHOLD) {
if (storage instanceof SparseSetStorage) {
QRTTableStorage bitSet = new BitSetQRTTableStorage(storage.maxSize());
bitSet.or(storage);
storage = bitSet;
}
} else if (storage instanceof BitSetQRTTableStorage) {
QRTTableStorage sparse = new SparseSetStorage(storage.maxSize());
sparse.or(storage);
storage = sparse;
}
}
public double getPercentFull() {
return storage.getPercentFull();
}
public int getUnitsInUse() {
return storage.getUnitsInUse();
}
public int getUnusedUnits() {
return storage.getUnusedUnits();
}
public int numUnitsWithLoad(int load) {
return storage.numUnitsWithLoad(load);
}
public void or(QRTTableStorage other) {
if (other instanceof DynamicQRTStorage)
other = ((DynamicQRTStorage)other).storage; // so we can optimize
storage.or(other);
}
public QRTTableStorage resize(int newSize) {
return storage.resize(newSize);
}
public void set(int hash) {
storage.set(hash);
}
public void xor(QRTTableStorage other) {
if (other instanceof DynamicQRTStorage)
other = ((DynamicQRTStorage)other).storage; // so we can optimize
storage.xor(other);
}
public int cardinality() {
return storage.cardinality();
}
public boolean get(int i) {
return storage.get(i);
}
public int maxSize() {
return storage.maxSize();
}
public int nextClearBit(int i) {
return storage.nextClearBit(i);
}
public int nextSetBit(int i) {
return storage.nextSetBit(i);
}
@Override
public DynamicQRTStorage clone() throws CloneNotSupportedException {
return new DynamicQRTStorage(storage.clone());
}
@Override
public boolean equals(Object o) {
if (o instanceof DynamicQRTStorage)
o = ((DynamicQRTStorage)o).storage;
return storage.equals(o);
}
public Iterator<Integer> iterator() {
return storage.iterator();
}
@Override
public String toString() {
return "DynamicQRTStorage: " + storage.toString();
}
}