package org.krakenapps.sqlengine.bdb; import java.nio.ByteBuffer; import java.util.HashSet; import java.util.Set; import org.krakenapps.codec.EncodingRule; import org.krakenapps.sqlengine.RowKey; import org.krakenapps.sqlengine.RowValue; import org.krakenapps.sqlengine.Status; import org.krakenapps.sqlengine.TableCursor; import org.krakenapps.sqlengine.TableHandle; import org.krakenapps.sqlengine.TableHandleEventListener; import com.sleepycat.je.Cursor; import com.sleepycat.je.CursorConfig; import com.sleepycat.je.Database; import com.sleepycat.je.DatabaseEntry; import com.sleepycat.je.LockMode; import com.sleepycat.je.OperationStatus; /** * Table handle is not thread-safe. * * @author xeraph * */ public class TableHandleImpl implements TableHandle { private Database db; private Set<TableHandleEventListener> callbacks; public TableHandleImpl(Database db) { this.db = db; this.callbacks = new HashSet<TableHandleEventListener>(); } @Override public TableCursor openCursor() { Cursor cursor = db.openCursor(null, new CursorConfig()); return new TableCursorImpl(cursor); } @Override public Status get(RowKey rowKey, RowValue rowValue) { DatabaseEntry k = encodeKey(rowKey.get()); DatabaseEntry v = new DatabaseEntry(); OperationStatus ret = db.get(null, k, v, LockMode.DEFAULT); if (ret == OperationStatus.SUCCESS) { ByteBuffer bb = ByteBuffer.wrap(v.getData()); Object[] data = EncodingRule.decodeArray(bb); rowValue.set(data); } return StatusConverter.convert(ret); } @Override public void insert(RowKey rowKey, RowValue rowValue) { DatabaseEntry k = encodeKey(rowKey.get()); DatabaseEntry v = encodeData(rowValue.getData()); db.put(null, k, v); } @Override public void update(RowKey rowKey, RowValue rowValue) { DatabaseEntry k = encodeKey(rowKey.get()); DatabaseEntry v = encodeData(rowValue.getData()); DatabaseEntry old = new DatabaseEntry(); OperationStatus ret = db.get(null, k, old, LockMode.DEFAULT); if (ret == OperationStatus.SUCCESS) db.delete(null, k); db.put(null, k, v); } @Override public void delete(RowKey rowKey) { DatabaseEntry k = encodeKey(rowKey.get()); db.delete(null, k); } private DatabaseEntry encodeData(Object[] data) { int len = EncodingRule.length(data); ByteBuffer bb = ByteBuffer.allocate(len); EncodingRule.encode(bb, data); DatabaseEntry v = new DatabaseEntry(bb.array()); return v; } private DatabaseEntry encodeKey(Object key) { ByteBuffer keybuf = ByteBuffer.allocate(EncodingRule.length(key)); EncodingRule.encode(keybuf, key); DatabaseEntry k = new DatabaseEntry(keybuf.array()); return k; } @Override public void addListener(TableHandleEventListener callback) { callbacks.add(callback); } @Override public void removeListener(TableHandleEventListener callback) { callbacks.remove(callback); } @Override public void close() { db.close(); // invoke close callbacks for (TableHandleEventListener callback : callbacks) callback.onClose(this); } }