package ch.unibe.scg.cells.hadoop;
import java.io.IOException;
import java.util.Map.Entry;
import javax.inject.Inject;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.ResultScanner;
import org.apache.hadoop.hbase.client.Scan;
import ch.unibe.scg.cells.Cell;
import ch.unibe.scg.cells.CellLookupTable;
import ch.unibe.scg.cells.hadoop.HBaseStorage.FamilyName;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableList.Builder;
import com.google.protobuf.ByteString;
/** Optimized for small row reads. */
class HBaseCellLookupTable<T> implements CellLookupTable<T> {
final private static long serialVersionUID = 1L;
final private SerializableHTable hTable;
/** Do not modify. */
final private byte[] family;
@Inject
HBaseCellLookupTable(SerializableHTable hTable, @FamilyName ByteString family) {
this.hTable = hTable;
this.family = family.toByteArray();
}
@Override
public Iterable<Cell<T>> readRow(ByteString rowPrefix) throws IOException {
byte[] from = rowPrefix.toByteArray();
// `To` is minimally greater than from, if possible.
byte[] to = rowPrefix.toByteArray();
boolean toGreaterThanFrom = false;
for (int i = from.length - 1; i >= 0; i--) {
if (to[i] != -1) { // -1 is the *lexicographically* highest byte.
to[i]++;
toGreaterThanFrom = true;
break;
}
}
Scan scan = new Scan(from, to); // Range: [from, to)
if (!toGreaterThanFrom) {
scan = new Scan(from); // Range: [from, inf)
}
scan.addFamily(family);
Builder<Cell<T>> ret = ImmutableList.builder();
try (ResultScanner scanner = hTable.hTable.getScanner(scan)) {
for (Result result = scanner.next(); result != null; result = scanner.next()) {
ByteString rowKey = ByteString.copyFrom(result.getRow());
for (Entry<byte[], byte[]> hbaseCell : result.getFamilyMap(family).entrySet()) {
ret.add(Cell.<T>make(
rowKey,
ByteString.copyFrom(hbaseCell.getKey()),
ByteString.copyFrom(hbaseCell.getValue())));
}
}
}
return ret.build();
}
@Override
public Iterable<Cell<T>> readColumn(ByteString columnKey) {
throw new RuntimeException("Not implemented");
}
@Override
public void close() throws IOException {
hTable.hTable.close();
}
}