package divconq.db.rocks.keyquery;
import org.rocksdb.RocksIterator;
import divconq.db.Constants;
import divconq.db.DatabaseException;
import divconq.db.rocks.RocksInterface;
import divconq.db.util.ByteUtil;
import divconq.lang.Memory;
import divconq.util.HexUtil;
public class KeyQuery {
protected KeyLevel first = null;
protected RocksInterface adapter = null;
protected RocksIterator it = null;
protected boolean browseMode = false;
protected byte[] key = null;
protected byte[] value = null;
public void setBrowseMode(boolean v) {
this.browseMode = v;
}
// levels pasted in may not be reused elsewhere, now owned/mutable by this object
public KeyQuery(RocksInterface adapter, KeyLevel... levels) {
if ((levels == null) || (levels.length == 0))
throw new IllegalArgumentException("KeyQuery missing levels");
this.adapter = adapter;
this.first = levels[0];
KeyLevel lastWild = null;
// setup the chain
for (int i = 1; i < levels.length; i++) {
levels[i-1].next = levels[i];
if (levels[i] instanceof WildcardKeyLevel)
lastWild = levels[i];
}
if (lastWild != null)
((WildcardKeyLevel)lastWild).setFinalWild(true);
this.it = this.adapter.iterator();
}
// return the key - null when done
public byte[] nextKey() {
if (!this.it.isValid())
this.it.seekToFirst();
else
this.it.next();
while (true) {
// because Query should never include omega, and db should always contain omega, this condition
// should never occur. KeyQuery should not be used to find Omega.
if (!this.it.isValid()) {
System.out.println(">>>>>> Key Query got to invalid position <<<<<<<<<<<<<<<<<");
return null;
}
byte[] key = this.it.key();
if (key[0] == Constants.DB_TYPE_MARKER_OMEGA) {
System.out.println(">>>>>> Key Query got to Omega <<<<<<<<<<<<<<<<<");
return null;
}
Memory keyMod = new Memory(key);
if (this.first.contains(key, this.browseMode, keyMod)) {
if (key.length > keyMod.getLength()) {
key = keyMod.toArray();
this.key = key;
try {
this.value = this.adapter.get(key);
}
catch (DatabaseException x) {
// TODO error msg
this.value = null;
}
if (this.value == null)
this.value = Constants.DB_EMPTY_ARRAY;
}
else {
this.key = key;
this.value = it.value();
}
return key;
}
byte[] nextkey = this.first.next();
if (nextkey == null) {
System.out.println(">>>>>> Key Query got no more suggestions <<<<<<<<<<<<<<<<<");
return null;
}
System.out.println("last key: " + HexUtil.bufferToHex(key));
System.out.println("sugg key: " + HexUtil.bufferToHex(nextkey));
// if nextkey <= current key return null because the key levels have run out of suggestions
if (ByteUtil.compareKeys(key, nextkey) >= 0) {
System.out.println(">>>>>> Key Query got stale suggestion <<<<<<<<<<<<<<<<<");
return null;
}
this.it.seek(nextkey);
}
}
public byte[] key() {
return this.key;
}
public byte[] value() {
return this.value;
}
}