Skip to content

Commit

Permalink
HBASE-22969 A new binary component comparator(BinaryComponentComparat…
Browse files Browse the repository at this point in the history
…or) to perform comparison of arbitrary length and position (#829)

Signed-off-by: Balazs Meszaros <meszibalu@apache.org>
  • Loading branch information
udaikashyap authored and meszibalu committed Nov 18, 2019
1 parent baf8849 commit ab63bde
Show file tree
Hide file tree
Showing 6 changed files with 497 additions and 0 deletions.
@@ -0,0 +1,125 @@
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.hadoop.hbase.filter;

import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;
import org.apache.hadoop.hbase.exceptions.DeserializationException;
import org.apache.hadoop.hbase.protobuf.generated.ComparatorProtos;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.yetus.audience.InterfaceAudience;

/**
* A comparator which compares against a specified byte array, but only
* compares specific portion of the byte array. For the rest it is similar to
* {@link BinaryComparator}.
*/
@InterfaceAudience.Public
@SuppressWarnings("ComparableType")
public class BinaryComponentComparator extends ByteArrayComparable {
private int offset; //offset of component from beginning.

/**
* Constructor
*
* @param value value of the component
* @param offset offset of the component from begining
*/
public BinaryComponentComparator(byte[] value, int offset) {
super(value);
this.offset = offset;
}

@Override
public int compareTo(byte[] value) {
return compareTo(value, 0, value.length);
}

@Override
public int compareTo(byte[] value, int offset, int length) {
return Bytes.compareTo(this.value, 0, this.value.length, value, offset + this.offset,
this.value.length);
}

@Override
public boolean equals(Object other) {
if (other == this){
return true;
}
if (!(other instanceof BinaryComponentComparator)){
return false;
}
BinaryComponentComparator bcc = (BinaryComponentComparator)other;
return offset == bcc.offset &&
(compareTo(bcc.value) == 0);
}

@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + offset;
return result;
}

/**
* @return The comparator serialized using pb
*/
@Override
public byte[] toByteArray() {
ComparatorProtos.BinaryComponentComparator.Builder builder =
ComparatorProtos.BinaryComponentComparator.newBuilder();
builder.setValue(ByteString.copyFrom(this.value));
builder.setOffset(this.offset);
return builder.build().toByteArray();
}

/**
* @param pbBytes A pb serialized {@link BinaryComponentComparator} instance
* @return An instance of {@link BinaryComponentComparator} made from <code>bytes</code>
* @throws DeserializationException DeserializationException
* @see #toByteArray
*/
public static BinaryComponentComparator parseFrom(final byte[] pbBytes)
throws DeserializationException {
ComparatorProtos.BinaryComponentComparator proto;
try {
proto = ComparatorProtos.BinaryComponentComparator.parseFrom(pbBytes);
} catch (InvalidProtocolBufferException e) {
throw new DeserializationException(e);
}
return new BinaryComponentComparator(proto.getValue().toByteArray(), proto.getOffset());
}

/**
* @param other paramemter to compare against
* @return true if and only if the fields of the comparator that are
* serialized are equal to the corresponding fields in other. Used for testing.
*/
@Override
boolean areSerializedFieldsEqual(ByteArrayComparable other) {
if (other == this){
return true;
}
if (!(other instanceof BinaryComponentComparator)){
return false;
}
return super.areSerializedFieldsEqual(other);
}
}
Expand Up @@ -104,6 +104,59 @@ public void testCellFieldsCompare() throws Exception {
assertTrue(PrivateCellUtil.qualifierStartsWith(kv, q1));
assertFalse(PrivateCellUtil.qualifierStartsWith(kv, q2));
assertFalse(PrivateCellUtil.qualifierStartsWith(kv, Bytes.toBytes("longerthanthequalifier")));

//Binary component comparisons
byte[] val = Bytes.toBytes("abcd");
kv = new KeyValue(r0, f, q1, val);
buffer = ByteBuffer.wrap(kv.getBuffer());
bbCell = new ByteBufferKeyValue(buffer, 0, buffer.remaining());

//equality check
//row comparison
//row is "row0"(set by variable r0)
//and we are checking for equality to 'o' at position 1
//'r' is at position 0.
byte[] component = Bytes.toBytes("o");
comparable = new BinaryComponentComparator(component, 1);
assertEquals(0, PrivateCellUtil.compareRow(bbCell, comparable));
assertEquals(0, PrivateCellUtil.compareRow(kv, comparable));
//value comparison
//value is "abcd"(set by variable val).
//and we are checking for equality to 'c' at position 2.
//'a' is at position 0.
component = Bytes.toBytes("c");
comparable = new BinaryComponentComparator(component, 2);
assertEquals(0,PrivateCellUtil.compareValue(bbCell, comparable));
assertEquals(0,PrivateCellUtil.compareValue(kv, comparable));

//greater than
component = Bytes.toBytes("z");
//checking for greater than at position 1.
//for both row("row0") and value("abcd")
//'z' > 'r'
comparable = new BinaryComponentComparator(component, 1);
//row comparison
assertTrue(PrivateCellUtil.compareRow(bbCell, comparable) > 0);
assertTrue(PrivateCellUtil.compareRow(kv, comparable) > 0);
//value comparison
//'z' > 'a'
assertTrue(PrivateCellUtil.compareValue(bbCell, comparable) > 0);
assertTrue(PrivateCellUtil.compareValue(kv, comparable) > 0);

//less than
component = Bytes.toBytes("a");
//checking for less than at position 1 for row ("row0")
comparable = new BinaryComponentComparator(component, 1);
//row comparison
//'a' < 'r'
assertTrue(PrivateCellUtil.compareRow(bbCell, comparable) < 0);
assertTrue(PrivateCellUtil.compareRow(kv, comparable) < 0);
//value comparison
//checking for less than at position 2 for value("abcd")
//'a' < 'c'
comparable = new BinaryComponentComparator(component, 2);
assertTrue(PrivateCellUtil.compareValue(bbCell, comparable) < 0);
assertTrue(PrivateCellUtil.compareValue(kv, comparable) < 0);
}

}
5 changes: 5 additions & 0 deletions hbase-protocol-shaded/src/main/protobuf/Comparator.proto
Expand Up @@ -77,3 +77,8 @@ message SubstringComparator {
message BigDecimalComparator {
required ByteArrayComparable comparable = 1;
}

message BinaryComponentComparator {
required bytes value = 1;
required uint32 offset = 2;
}
5 changes: 5 additions & 0 deletions hbase-protocol/src/main/protobuf/Comparator.proto
Expand Up @@ -76,3 +76,8 @@ message SubstringComparator {
message BigDecimalComparator {
required ByteArrayComparable comparable = 1;
}

message BinaryComponentComparator {
required bytes value = 1;
required uint32 offset = 2;
}

0 comments on commit ab63bde

Please sign in to comment.