package edu.uncc.cs.watsonsim;
import static org.fusesource.lmdbjni.Constants.bytes;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.Optional;
import java.util.function.Function;
import org.fusesource.lmdbjni.Constants;
import org.fusesource.lmdbjni.Env;
import org.fusesource.lmdbjni.Transaction;
public class KV {
public Env db = new Env();
public KV() {
db.open("data/lmdb", org.fusesource.lmdbjni.Constants.CREATE);
}
/**
* Get a byte array from the database just as it was stored.
* @param table Which table to retrieve it from
* @param key Which key you want
* @return byte[]
*/
public Optional<byte[]> get(String table, String key) {
return Optional.ofNullable(db.openDatabase(table).get(bytes(key)));
}
/**
* Basically just does ((float[]) bytes) which is moderately complex.
* @param bytes
* @return
*/
public static float[] asVector(byte[] bytes) {
FloatBuffer fb = FloatBuffer.allocate((bytes.length + 3) / 4);
fb.put(ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).asFloatBuffer());
return fb.array();
}
/**
* Basically just does ((byte[]) floats) which is moderately complex.
* @param bytes
* @return
*/
public static byte[] asBytes(float[] floats) {
ByteBuffer bb = ByteBuffer.wrap(new byte[floats.length*4]).order(ByteOrder.LITTLE_ENDIAN);
bb.asFloatBuffer().put(floats);
return bb.array();
}
/**
* Non-atomically update an entry or return it.
* This is used for cases reading is common (getting a fast path
* with only a read lock) but writing is not (and might be run twice).
*/
public String quickGetOrCompute(String table, String key, Function<String, String> comp) {
return get(table, key).map(Constants::string).orElseGet(() -> {
try (Transaction tx = db.createWriteTransaction()){
String o = comp.apply(key);
db.openDatabase(tx, table, 0).put(bytes(key), bytes(o));
return o;
}
});
}
}