package mil.nga.giat.geowave.datastore.hbase.query;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Arrays;
import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.CellUtil;
import org.apache.hadoop.hbase.exceptions.DeserializationException;
import org.apache.hadoop.hbase.filter.Filter;
import org.apache.hadoop.hbase.filter.FilterBase;
import org.apache.hadoop.hbase.util.ByteStringer;
import com.google.protobuf.InvalidProtocolBufferException;
import mil.nga.giat.geowave.datastore.hbase.query.protobuf.FilterProtos;
/**
* This is a Filter which will run on Tablet Server during Scan. HBase uses
* these filters instead of Iterators. It makes use of Protocol Buffer library
* See {@link https ://developers.google.com/protocol-buffers/docs/javatutorial}
* for more info.
*/
public class SingleEntryFilter extends
FilterBase
{
public static final String ADAPTER_ID = "adapterid";
public static final String DATA_ID = "dataid";
private final byte[] adapterId;
private final byte[] dataId;
public SingleEntryFilter(
final byte[] dataId,
final byte[] adapterId ) {
if (adapterId == null) {
throw new IllegalArgumentException(
"'adapterid' must be set for " + SingleEntryFilter.class.getName());
}
if (dataId == null) {
throw new IllegalArgumentException(
"'dataid' must be set for " + SingleEntryFilter.class.getName());
}
this.adapterId = adapterId;
this.dataId = dataId;
}
@Override
public ReturnCode filterKeyValue(
final Cell v )
throws IOException {
boolean accept = true;
final byte[] localAdapterId = CellUtil.cloneFamily(v);
if (Arrays.equals(
localAdapterId,
adapterId)) {
final byte[] rowId = CellUtil.cloneRow(v);
final byte[] metadata = Arrays.copyOfRange(
rowId,
rowId.length - 12,
rowId.length);
final ByteBuffer metadataBuf = ByteBuffer.wrap(metadata);
final int adapterIdLength = metadataBuf.getInt();
final int dataIdLength = metadataBuf.getInt();
final ByteBuffer buf = ByteBuffer.wrap(
rowId,
0,
rowId.length - 12);
final byte[] indexId = new byte[rowId.length - 12 - adapterIdLength - dataIdLength];
final byte[] rawAdapterId = new byte[adapterIdLength];
final byte[] rawDataId = new byte[dataIdLength];
buf.get(indexId);
buf.get(rawAdapterId);
buf.get(rawDataId);
if (!Arrays.equals(
rawDataId,
dataId) && Arrays.equals(
rawAdapterId,
adapterId)) {
accept = false;
}
}
else {
accept = false;
}
return accept ? ReturnCode.INCLUDE : ReturnCode.SKIP;
}
public static Filter parseFrom(
final byte[] pbBytes )
throws DeserializationException {
FilterProtos.SingleEntryFilter proto;
try {
proto = FilterProtos.SingleEntryFilter.parseFrom(pbBytes);
}
catch (final InvalidProtocolBufferException e) {
throw new DeserializationException(
e);
}
return new SingleEntryFilter(
proto.getDataId().toByteArray(),
proto.getAdapterId().toByteArray());
}
@Override
public byte[] toByteArray() {
final FilterProtos.SingleEntryFilter.Builder builder = FilterProtos.SingleEntryFilter.newBuilder();
if (adapterId != null) {
builder.setAdapterId(ByteStringer.wrap(adapterId));
}
if (dataId != null) {
builder.setDataId(ByteStringer.wrap(dataId));
}
return builder.build().toByteArray();
}
}