package divconq.db.rocks;
import org.rocksdb.RocksDB;
import org.rocksdb.RocksDBException;
import org.rocksdb.RocksIterator;
import divconq.db.Constants;
import divconq.db.DatabaseException;
import divconq.db.DatabaseInterface;
import divconq.db.util.ByteUtil;
import divconq.lang.Memory;
import divconq.lang.op.OperationContext;
public class RocksInterface extends DatabaseInterface {
protected DatabaseManager dbman = null;
protected RocksDB db = null;
public RocksInterface(DatabaseManager dbman) {
this.dbman = dbman;
this.db = dbman.db;
}
public RocksIterator iterator() {
return this.db.newIterator();
}
public byte[] get(byte[] key) throws DatabaseException {
try {
return this.db.get(key);
}
catch (RocksDBException x) {
throw new DatabaseException(x);
}
}
@Override
public void put(byte[] key, byte[] value) throws DatabaseException {
try {
this.db.put(key, value);
}
catch (RocksDBException x) {
throw new DatabaseException(x);
}
}
@Override
public boolean isAuditDisabled() {
return this.dbman.isAuditDisabled();
}
@Override
public Long inc(byte[] key, int amt) throws DatabaseException {
try {
return this.dbman.inc(key, amt);
}
catch (RocksDBException x) {
throw new DatabaseException(x);
}
}
@Override
public boolean isSet(byte[] key) throws DatabaseException {
RocksIterator it = this.db.newIterator();
it.seek(key);
// found an exact match
boolean ret = (ByteUtil.compareKeys(it.key(), key) == 0);
it.dispose();
return ret;
}
@Override
public String allocateSubkey() {
return this.dbman.allocateSubkey();
}
@Override
public boolean hasAny(byte[] key) throws DatabaseException {
RocksIterator it = this.db.newIterator();
it.seek(key);
// found an sub match or exact match
boolean ret = ByteUtil.keyStartsWith(it.key(), key);
it.dispose();
return ret;
}
@Override
public byte[] getOrNextPeerKey(byte[] key, byte[] peer) throws DatabaseException {
RocksIterator it = this.db.newIterator();
if (peer == null)
peer = Constants.DB_EMPTY_ARRAY;
Memory mem = new Memory(key.length + 1 + peer.length);
mem.write(key);
mem.writeByte(Constants.DB_TYPE_MARKER_ALPHA);
mem.write(peer);
it.seek(mem.getBufferEntry(0));
if (!it.isValid()) {
it.dispose();
return null;
}
byte[] fnd = it.key();
it.dispose();
// match not found, peer key doesn't exist at all and was skipped
if (!ByteUtil.keyStartsWith(fnd, key))
return null;
mem = new Memory(fnd);
mem.setPosition(key.length + 1);
// return just 1 part - it might the same as peer or it might be the next peer
return ByteUtil.extractNextDirect(mem);
}
@Override
public byte[] getOrPrevPeerKey(byte[] key, byte[] peer) throws DatabaseException {
RocksIterator it = this.db.newIterator();
if (peer == null)
peer = Constants.DB_OMEGA_MARKER_ARRAY;
Memory mem = new Memory(key.length + 1 + peer.length);
mem.write(key);
mem.writeByte(Constants.DB_TYPE_MARKER_ALPHA);
mem.write(peer);
it.seek(mem.getBufferEntry(0));
if (it.isValid()) {
byte[] fnd = it.key();
/*
// ------------- TODO --------------
System.out.println("looking for match: " + HexUtil.bufferToHex(key));
System.out.println(" before: " + HexUtil.bufferToHex(mem.getBufferEntry(0)));
System.out.println(" got: " + HexUtil.bufferToHex(fnd));
// ---------------------------------
*/
// match found, peer key exists
if (ByteUtil.keyStartsWith(fnd, key)) {
mem = new Memory(fnd);
mem.setPosition(key.length + 1);
it.dispose();
// ------------- TODO --------------
/*
List<Object> keyParts = ByteUtil.extractKeyParts(fnd);
for (Object p : keyParts)
System.out.print((p == null) ? " / " : p.toString() + " / ");
System.out.println();
*/
// ---------------------------------
// return just 1 part - it might the same as peer or it might be the next peer
return ByteUtil.extractNextDirect(mem);
}
}
// otherwise peer does not exist at all, go back 1
it.prev();
if (!it.isValid()) {
it.dispose();
return null;
}
byte[] fnd = it.key();
it.dispose();
// ------------- TODO --------------
/*
System.out.println("looking for match: " + HexUtil.bufferToHex(key));
System.out.println(" before: " + HexUtil.bufferToHex(mem.getBufferEntry(0)));
System.out.println(" got: " + HexUtil.bufferToHex(fnd));
*/
// ---------------------------------
// match found, prev peer key exists
if (ByteUtil.keyStartsWith(fnd, key)) {
mem = new Memory(fnd);
mem.setPosition(key.length + 1);
// ------------- TODO --------------
/*
List<Object> keyParts = ByteUtil.extractKeyParts(fnd);
for (Object p : keyParts)
System.out.print((p == null) ? " / " : p.toString() + " / ");
System.out.println();
*/
// ---------------------------------
// return just 1 part - it might the same as peer or it might be the next peer
return ByteUtil.extractNextDirect(mem);
}
return null;
}
@Override
public byte[] nextPeerKey(byte[] key, byte[] peer) throws DatabaseException {
RocksIterator it = this.db.newIterator();
//if (peer == null)
// peer = Constants.DB_EMPTY_ARRAY;
int len = 1;
if (key != null)
len += key.length + 1;
if (peer != null)
len += peer.length;
Memory mem = new Memory(len);
if (key != null) {
mem.write(key);
mem.writeByte(Constants.DB_TYPE_MARKER_ALPHA);
}
if (peer != null)
mem.write(peer);
mem.writeByte((byte)0x01); // forces us to look for next key - all subkeys of peer are skipped
//System.out.println("Next on: " + HexUtil.bufferToHex(mem.getBufferEntry(0)));
it.seek(mem.getBufferEntry(0));
if (!it.isValid()) {
it.dispose();
return null;
}
byte[] fnd = it.key();
//System.out.println("Next fnd: " + HexUtil.bufferToHex(fnd));
it.dispose();
//System.out.println("looking for match: " + HexUtil.bufferToHex(key));
//System.out.println(" after: " + HexUtil.bufferToHex(peer));
//System.out.println(" got: " + HexUtil.bufferToHex(fnd));
// match not found, next peer key doesn't exist at all and was skipped
if ((key != null) && !ByteUtil.keyStartsWith(fnd, key))
return null;
//System.out.println("match!");
mem = new Memory(fnd);
mem.setPosition((key == null) ? 0 : key.length + 1);
// return just 1 part - the next peer
return ByteUtil.extractNextDirect(mem);
}
@Override
public byte[] prevPeerKey(byte[] key, byte[] peer) throws DatabaseException {
RocksIterator it = this.db.newIterator();
if (peer == null)
peer = Constants.DB_OMEGA_MARKER_ARRAY;
Memory mem = new Memory(key.length + 1 + peer.length);
mem.write(key);
mem.writeByte(Constants.DB_TYPE_MARKER_ALPHA);
mem.write(peer);
it.seek(mem.getBufferEntry(0));
/*
if (!it.isValid()) {
it.dispose();
return null;
}
byte[] fnd2 = it.key();
// ------------- TODO --------------
System.out.println("looking for match: " + HexUtil.bufferToHex(key));
System.out.println(" before: " + HexUtil.bufferToHex(mem.getBufferEntry(0)));
System.out.println(" got: " + HexUtil.bufferToHex(fnd2));
List<Object> keyParts2 = ByteUtil.extractKeyParts(fnd2);
for (Object p : keyParts2)
System.out.print((p == null) ? " / " : p.toString() + " / ");
System.out.println();
*/
// ---------------------------------
// regardless if peer exists or does not exist, go back 1 key
it.prev();
if (!it.isValid()) {
it.dispose();
return null;
}
byte[] fnd = it.key();
// ------------- TODO --------------
/*
System.out.println(" got 2: " + HexUtil.bufferToHex(fnd));
List<Object> keyParts = ByteUtil.extractKeyParts(fnd);
for (Object p : keyParts)
System.out.print((p == null) ? " / " : p.toString() + " / ");
System.out.println();
*/
// ---------------------------------
it.dispose();
// match found, prev peer key exists
if (ByteUtil.keyStartsWith(fnd, key)) {
mem = new Memory(fnd);
mem.setPosition(key.length + 1);
//System.out.println("match!");
// return just 1 part - it might the same as peer or it might be the next peer
return ByteUtil.extractNextDirect(mem);
}
//System.out.println("no match!");
return null;
}
@Override
public void kill(byte[] key) {
RocksIterator it = this.db.newIterator();
it.seek(key);
while (ByteUtil.keyStartsWith(it.key(), key)) {
try {
db.remove(it.key());
}
catch (RocksDBException x) {
OperationContext.get().error("Error removing key: " + x);
}
it.next();
}
it.dispose();
}
}