package ezdb.treemap; import java.util.Comparator; import java.util.Iterator; import java.util.Map; import java.util.NavigableMap; import java.util.TreeMap; import ezdb.DbException; import ezdb.RangeTable; import ezdb.RawTableRow; import ezdb.TableIterator; import ezdb.TableRow; import ezdb.batch.Batch; import ezdb.batch.RangeBatch; import ezdb.serde.Serde; import ezdb.util.Util; public class TreeMapTable<H, R, V> implements RangeTable<H, R, V> { private final Serde<H> hashKeySerde; private final Serde<R> rangeKeySerde; private final Serde<V> valueSerde; private final NavigableMap<byte[], byte[]> map; private final Comparator<byte[]> hashKeyComparator; public TreeMapTable(Serde<H> hashKeySerde, Serde<R> rangeKeySerde, Serde<V> valueSerde, final Comparator<byte[]> hashKeyComparator, final Comparator<byte[]> rangeKeyComparator) { this.hashKeySerde = hashKeySerde; this.rangeKeySerde = rangeKeySerde; this.valueSerde = valueSerde; this.hashKeyComparator = hashKeyComparator; this.map = new TreeMap<byte[], byte[]>(new Comparator<byte[]>() { @Override public int compare(byte[] k1, byte[] k2) { return Util.compareKeys(hashKeyComparator, rangeKeyComparator, k1, k2); } }); } @Override public void put(H hashKey, V value) { put(hashKey, null, value); } @Override public V get(H hashKey) { return get(hashKey, null); } @Override public void put(H hashKey, R rangeKey, V value) { map.put(Util.combine(hashKeySerde, rangeKeySerde, hashKey, rangeKey), valueSerde.toBytes(value)); } @Override public V get(H hashKey, R rangeKey) { byte[] valueBytes = map.get(Util.combine(hashKeySerde, rangeKeySerde, hashKey, rangeKey)); if (valueBytes != null) { return valueSerde.fromBytes(valueBytes); } return null; } @Override public TableIterator<H, R, V> range(H hashKey) { final byte[] keyBytesFrom = Util.combine(hashKeySerde, rangeKeySerde, hashKey, null); final Iterator<Map.Entry<byte[], byte[]>> iterator = map .tailMap(keyBytesFrom).entrySet().iterator(); return new TableIterator<H, R, V>() { Map.Entry<byte[], byte[]> next = (iterator.hasNext()) ? iterator .next() : null; @Override public boolean hasNext() { return next != null && Util.compareKeys(hashKeyComparator, null, keyBytesFrom, next.getKey()) == 0; } @Override public TableRow<H, R, V> next() { TableRow<H, R, V> row = null; if (hasNext()) { row = new RawTableRow<H, R, V>(next, hashKeySerde, rangeKeySerde, valueSerde); } if (iterator.hasNext()) { next = iterator.next(); } else { next = null; } if (row != null) { return row; } else { throw new DbException(new NoSuchMethodException()); } } @Override public void remove() { iterator.remove(); } @Override public void close() { } }; } @Override public TableIterator<H, R, V> range(H hashKey, R fromRangeKey) { final byte[] keyBytesFrom = Util.combine(hashKeySerde, rangeKeySerde, hashKey, fromRangeKey); final Iterator<Map.Entry<byte[], byte[]>> iterator = map .tailMap(keyBytesFrom).entrySet().iterator(); return new TableIterator<H, R, V>() { Map.Entry<byte[], byte[]> next = (iterator.hasNext()) ? iterator .next() : null; @Override public boolean hasNext() { return next != null && Util.compareKeys(hashKeyComparator, null, keyBytesFrom, next.getKey()) == 0; } @Override public TableRow<H, R, V> next() { RawTableRow<H, R, V> row = null; if (hasNext()) { row = new RawTableRow<H, R, V>(next, hashKeySerde, rangeKeySerde, valueSerde); } if (iterator.hasNext()) { next = iterator.next(); } else { next = null; } if (row != null) { return row; } else { throw new DbException(new NoSuchMethodException()); } } @Override public void remove() { iterator.remove(); } @Override public void close() { } }; } @Override public TableIterator<H, R, V> range(H hashKey, R fromRangeKey, R toRangeKey) { final byte[] keyBytesFrom = Util.combine(hashKeySerde, rangeKeySerde, hashKey, fromRangeKey); final byte[] keyBytesTo = Util.combine(hashKeySerde, rangeKeySerde, hashKey, toRangeKey); final Iterator<Map.Entry<byte[], byte[]>> iterator = map .subMap(keyBytesFrom, true, keyBytesTo, false).entrySet() .iterator(); return new TableIterator<H, R, V>() { Map.Entry<byte[], byte[]> next = (iterator.hasNext()) ? iterator .next() : null; @Override public boolean hasNext() { return next != null; } @Override public TableRow<H, R, V> next() { RawTableRow<H, R, V> row = null; if (hasNext()) { row = new RawTableRow<H, R, V>(next, hashKeySerde, rangeKeySerde, valueSerde); } if (iterator.hasNext()) { next = iterator.next(); } else { next = null; } if (row != null) { return row; } else { throw new DbException(new NoSuchMethodException()); } } @Override public void remove() { iterator.remove(); } @Override public void close() { } }; } @Override public void delete(H hashKey) { delete(hashKey, null); } @Override public void delete(H hashKey, R rangeKey) { map.remove(Util.combine(hashKeySerde, rangeKeySerde, hashKey, rangeKey)); } @Override public void close() { } @Override public TableIterator<H, R, V> rangeReverse(H hashKey) { throw new UnsupportedOperationException(); } @Override public TableIterator<H, R, V> rangeReverse(H hashKey, R fromRangeKey) { throw new UnsupportedOperationException(); } @Override public TableIterator<H, R, V> rangeReverse(H hashKey, R fromRangeKey, R toRangeKey) { throw new UnsupportedOperationException(); } @Override public TableRow<H, R, V> getLatest(H hashKey) { throw new UnsupportedOperationException(); } @Override public TableRow<H, R, V> getLatest(H hashKey, R rangeKey) { throw new UnsupportedOperationException(); } @Override public TableRow<H, R, V> getNext(H hashKey, R rangeKey) { throw new UnsupportedOperationException(); } @Override public TableRow<H, R, V> getPrev(H hashKey, R rangeKey) { throw new UnsupportedOperationException(); } @Override public Batch<H, V> newBatch() { throw new UnsupportedOperationException(); } @Override public RangeBatch<H, R, V> newRangeBatch() { throw new UnsupportedOperationException(); } @Override public void deleteRange(H hashKey) { TableIterator<H, R, V> range = range(hashKey); while(range.hasNext()){ TableRow<H, R, V> next = range.next(); delete(next.getHashKey(), next.getRangeKey()); } } @Override public void deleteRange(H hashKey, R fromRangeKey) { TableIterator<H, R, V> range = range(hashKey, fromRangeKey); while(range.hasNext()){ TableRow<H, R, V> next = range.next(); delete(next.getHashKey(), next.getRangeKey()); } } @Override public void deleteRange(H hashKey, R fromRangeKey, R toRangeKey) { TableIterator<H, R, V> range = range(hashKey, fromRangeKey, toRangeKey); while(range.hasNext()){ TableRow<H, R, V> next = range.next(); delete(next.getHashKey(), next.getRangeKey()); } } }