You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by te...@apache.org on 2013/01/24 19:13:56 UTC
svn commit: r1438114 - in /hbase/branches/0.94/src:
main/java/org/apache/hadoop/hbase/filter/
main/java/org/apache/hadoop/hbase/io/
test/java/org/apache/hadoop/hbase/filter/
test/java/org/apache/hadoop/hbase/io/
Author: tedyu
Date: Thu Jan 24 18:13:55 2013
New Revision: 1438114
URL: http://svn.apache.org/viewvc?rev=1438114&view=rev
Log:
HBASE-7628 Port HBASE-6509 fast-forwarding FuzzyRowFilter to 0.94 (Anoop)
Added:
hbase/branches/0.94/src/main/java/org/apache/hadoop/hbase/filter/FuzzyRowFilter.java
hbase/branches/0.94/src/test/java/org/apache/hadoop/hbase/filter/TestFuzzyRowFilter.java
Modified:
hbase/branches/0.94/src/main/java/org/apache/hadoop/hbase/io/HbaseObjectWritable.java
hbase/branches/0.94/src/test/java/org/apache/hadoop/hbase/io/TestHbaseObjectWritable.java
Added: hbase/branches/0.94/src/main/java/org/apache/hadoop/hbase/filter/FuzzyRowFilter.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.94/src/main/java/org/apache/hadoop/hbase/filter/FuzzyRowFilter.java?rev=1438114&view=auto
==============================================================================
--- hbase/branches/0.94/src/main/java/org/apache/hadoop/hbase/filter/FuzzyRowFilter.java (added)
+++ hbase/branches/0.94/src/main/java/org/apache/hadoop/hbase/filter/FuzzyRowFilter.java Thu Jan 24 18:13:55 2013
@@ -0,0 +1,289 @@
+/**
+ * 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 java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.hadoop.hbase.KeyValue;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.hadoop.hbase.util.Pair;
+
+/**
+ * Filters data based on fuzzy row key. Performs fast-forwards during scanning.
+ * It takes pairs (row key, fuzzy info) to match row keys. Where fuzzy info is
+ * a byte array with 0 or 1 as its values:
+ * <ul>
+ * <li>
+ * 0 - means that this byte in provided row key is fixed, i.e. row key's byte at same position
+ * must match
+ * </li>
+ * <li>
+ * 1 - means that this byte in provided row key is NOT fixed, i.e. row key's byte at this
+ * position can be different from the one in provided row key
+ * </li>
+ * </ul>
+ *
+ *
+ * Example:
+ * Let's assume row key format is userId_actionId_year_month. Length of userId is fixed
+ * and is 4, length of actionId is 2 and year and month are 4 and 2 bytes long respectively.
+ *
+ * Let's assume that we need to fetch all users that performed certain action (encoded as "99")
+ * in Jan of any year. Then the pair (row key, fuzzy info) would be the following:
+ * row key = "????_99_????_01" (one can use any value instead of "?")
+ * fuzzy info = "\x01\x01\x01\x01\x00\x00\x00\x00\x01\x01\x01\x01\x00\x00\x00"
+ *
+ * I.e. fuzzy info tells the matching mask is "????_99_????_01", where at ? can be any value.
+ *
+ */
+public class FuzzyRowFilter extends FilterBase {
+ private List<Pair<byte[], byte[]>> fuzzyKeysData;
+ private boolean done = false;
+
+ /**
+ * Used internally for reflection, do NOT use it directly
+ */
+ public FuzzyRowFilter() {
+ }
+
+ public FuzzyRowFilter(List<Pair<byte[], byte[]>> fuzzyKeysData) {
+ this.fuzzyKeysData = fuzzyKeysData;
+ }
+
+ // TODO: possible improvement: save which fuzzy row key to use when providing a hint
+ @Override
+ public ReturnCode filterKeyValue(KeyValue kv) {
+ byte[] rowKey = kv.getRow();
+ // assigning "worst" result first and looking for better options
+ SatisfiesCode bestOption = SatisfiesCode.NO_NEXT;
+ for (Pair<byte[], byte[]> fuzzyData : fuzzyKeysData) {
+ SatisfiesCode satisfiesCode =
+ satisfies(rowKey, fuzzyData.getFirst(), fuzzyData.getSecond());
+ if (satisfiesCode == SatisfiesCode.YES) {
+ return ReturnCode.INCLUDE;
+ }
+
+ if (satisfiesCode == SatisfiesCode.NEXT_EXISTS) {
+ bestOption = SatisfiesCode.NEXT_EXISTS;
+ }
+ }
+
+ if (bestOption == SatisfiesCode.NEXT_EXISTS) {
+ return ReturnCode.SEEK_NEXT_USING_HINT;
+ }
+
+ // the only unhandled SatisfiesCode is NO_NEXT, i.e. we are done
+ done = true;
+ return ReturnCode.NEXT_ROW;
+ }
+
+ @Override
+ public KeyValue getNextKeyHint(KeyValue currentKV) {
+ byte[] rowKey = currentKV.getRow();
+ byte[] nextRowKey = null;
+ // Searching for the "smallest" row key that satisfies at least one fuzzy row key
+ for (Pair<byte[], byte[]> fuzzyData : fuzzyKeysData) {
+ byte[] nextRowKeyCandidate = getNextForFuzzyRule(rowKey,
+ fuzzyData.getFirst(), fuzzyData.getSecond());
+ if (nextRowKeyCandidate == null) {
+ continue;
+ }
+ if (nextRowKey == null || Bytes.compareTo(nextRowKeyCandidate, nextRowKey) < 0) {
+ nextRowKey = nextRowKeyCandidate;
+ }
+ }
+
+ if (nextRowKey == null) {
+ // SHOULD NEVER happen
+ // TODO: is there a better way than throw exception? (stop the scanner?)
+ throw new IllegalStateException("No next row key that satisfies fuzzy exists when" +
+ " getNextKeyHint() is invoked." +
+ " Filter: " + this.toString() +
+ " currentKV: " + currentKV.toString());
+ }
+
+ return KeyValue.createFirstOnRow(nextRowKey);
+ }
+
+ @Override
+ public boolean filterAllRemaining() {
+ return done;
+ }
+
+ @Override
+ public void write(DataOutput dataOutput) throws IOException {
+ dataOutput.writeInt(this.fuzzyKeysData.size());
+ for (Pair<byte[], byte[]> fuzzyData : fuzzyKeysData) {
+ Bytes.writeByteArray(dataOutput, fuzzyData.getFirst());
+ Bytes.writeByteArray(dataOutput, fuzzyData.getSecond());
+ }
+ }
+
+ @Override
+ public void readFields(DataInput dataInput) throws IOException {
+ int count = dataInput.readInt();
+ this.fuzzyKeysData = new ArrayList<Pair<byte[], byte[]>>(count);
+ for (int i = 0; i < count; i++) {
+ byte[] keyBytes = Bytes.readByteArray(dataInput);
+ byte[] keyMeta = Bytes.readByteArray(dataInput);
+ this.fuzzyKeysData.add(new Pair<byte[], byte[]>(keyBytes, keyMeta));
+ }
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("FuzzyRowFilter");
+ sb.append("{fuzzyKeysData=");
+ for (Pair<byte[], byte[]> fuzzyData : fuzzyKeysData) {
+ sb.append('{').append(Bytes.toStringBinary(fuzzyData.getFirst())).append(":");
+ sb.append(Bytes.toStringBinary(fuzzyData.getSecond())).append('}');
+ }
+ sb.append("}, ");
+ return sb.toString();
+ }
+
+ // Utility methods
+
+ static enum SatisfiesCode {
+ // row satisfies fuzzy rule
+ YES,
+ // row doesn't satisfy fuzzy rule, but there's possible greater row that does
+ NEXT_EXISTS,
+ // row doesn't satisfy fuzzy rule and there's no greater row that does
+ NO_NEXT
+ }
+
+ static SatisfiesCode satisfies(byte[] row,
+ byte[] fuzzyKeyBytes, byte[] fuzzyKeyMeta) {
+ return satisfies(row, 0, row.length, fuzzyKeyBytes, fuzzyKeyMeta);
+ }
+
+ private static SatisfiesCode satisfies(byte[] row, int offset, int length,
+ byte[] fuzzyKeyBytes, byte[] fuzzyKeyMeta) {
+ if (row == null) {
+ // do nothing, let scan to proceed
+ return SatisfiesCode.YES;
+ }
+
+ boolean nextRowKeyCandidateExists = false;
+
+ for (int i = 0; i < fuzzyKeyMeta.length && i < length; i++) {
+ // First, checking if this position is fixed and not equals the given one
+ boolean byteAtPositionFixed = fuzzyKeyMeta[i] == 0;
+ boolean fixedByteIncorrect = byteAtPositionFixed && fuzzyKeyBytes[i] != row[i + offset];
+ if (fixedByteIncorrect) {
+ // in this case there's another row that satisfies fuzzy rule and bigger than this row
+ if (nextRowKeyCandidateExists) {
+ return SatisfiesCode.NEXT_EXISTS;
+ }
+
+ // If this row byte is less than fixed then there's a byte array bigger than
+ // this row and which satisfies the fuzzy rule. Otherwise there's no such byte array:
+ // this row is simply bigger than any byte array that satisfies the fuzzy rule
+ boolean rowByteLessThanFixed = (row[i + offset] & 0xFF) < (fuzzyKeyBytes[i] & 0xFF);
+ return rowByteLessThanFixed ? SatisfiesCode.NEXT_EXISTS : SatisfiesCode.NO_NEXT;
+ }
+
+ // Second, checking if this position is not fixed and byte value is not the biggest. In this
+ // case there's a byte array bigger than this row and which satisfies the fuzzy rule. To get
+ // bigger byte array that satisfies the rule we need to just increase this byte
+ // (see the code of getNextForFuzzyRule below) by one.
+ // Note: if non-fixed byte is already at biggest value, this doesn't allow us to say there's
+ // bigger one that satisfies the rule as it can't be increased.
+ if (fuzzyKeyMeta[i] == 1 && !isMax(fuzzyKeyBytes[i])) {
+ nextRowKeyCandidateExists = true;
+ }
+ }
+
+ return SatisfiesCode.YES;
+ }
+
+ private static boolean isMax(byte fuzzyKeyByte) {
+ return (fuzzyKeyByte & 0xFF) == 255;
+ }
+
+ static byte[] getNextForFuzzyRule(byte[] row, byte[] fuzzyKeyBytes, byte[] fuzzyKeyMeta) {
+ return getNextForFuzzyRule(row, 0, row.length, fuzzyKeyBytes, fuzzyKeyMeta);
+ }
+
+ /**
+ * @return greater byte array than given (row) which satisfies the fuzzy rule if it exists,
+ * null otherwise
+ */
+ private static byte[] getNextForFuzzyRule(byte[] row, int offset, int length,
+ byte[] fuzzyKeyBytes, byte[] fuzzyKeyMeta) {
+ // To find out the next "smallest" byte array that satisfies fuzzy rule and "greater" than
+ // the given one we do the following:
+ // 1. setting values on all "fixed" positions to the values from fuzzyKeyBytes
+ // 2. if during the first step given row did not increase, then we increase the value at
+ // the first "non-fixed" position (where it is not maximum already)
+
+ // It is easier to perform this by using fuzzyKeyBytes copy and setting "non-fixed" position
+ // values than otherwise.
+ byte[] result = Arrays.copyOf(fuzzyKeyBytes,
+ length > fuzzyKeyBytes.length ? length : fuzzyKeyBytes.length);
+ int toInc = -1;
+
+ boolean increased = false;
+ for (int i = 0; i < result.length; i++) {
+ if (i >= fuzzyKeyMeta.length || fuzzyKeyMeta[i] == 1) {
+ result[i] = row[offset + i];
+ if (!isMax(row[i])) {
+ // this is "non-fixed" position and is not at max value, hence we can increase it
+ toInc = i;
+ }
+ } else if (i < fuzzyKeyMeta.length && fuzzyKeyMeta[i] == 0) {
+ if ((row[i + offset] & 0xFF) < (fuzzyKeyBytes[i] & 0xFF)) {
+ // if setting value for any fixed position increased the original array,
+ // we are OK
+ increased = true;
+ break;
+ }
+ if ((row[i + offset] & 0xFF) > (fuzzyKeyBytes[i] & 0xFF)) {
+ // if setting value for any fixed position makes array "smaller", then just stop:
+ // in case we found some non-fixed position to increase we will do it, otherwise
+ // there's no "next" row key that satisfies fuzzy rule and "greater" than given row
+ break;
+ }
+ }
+ }
+
+ if (!increased) {
+ if (toInc < 0) {
+ return null;
+ }
+ result[toInc]++;
+
+ // Setting all "non-fixed" positions to zeroes to the right of the one we increased so
+ // that found "next" row key is the smallest possible
+ for (int i = toInc + 1; i < result.length; i++) {
+ if (i >= fuzzyKeyMeta.length || fuzzyKeyMeta[i] == 1) {
+ result[i] = 0;
+ }
+ }
+ }
+
+ return result;
+ }
+}
Modified: hbase/branches/0.94/src/main/java/org/apache/hadoop/hbase/io/HbaseObjectWritable.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.94/src/main/java/org/apache/hadoop/hbase/io/HbaseObjectWritable.java?rev=1438114&r1=1438113&r2=1438114&view=diff
==============================================================================
--- hbase/branches/0.94/src/main/java/org/apache/hadoop/hbase/io/HbaseObjectWritable.java (original)
+++ hbase/branches/0.94/src/main/java/org/apache/hadoop/hbase/io/HbaseObjectWritable.java Thu Jan 24 18:13:55 2013
@@ -72,6 +72,7 @@ import org.apache.hadoop.hbase.filter.Co
import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
import org.apache.hadoop.hbase.filter.DependentColumnFilter;
import org.apache.hadoop.hbase.filter.FirstKeyOnlyFilter;
+import org.apache.hadoop.hbase.filter.FuzzyRowFilter;
import org.apache.hadoop.hbase.filter.InclusiveStopFilter;
import org.apache.hadoop.hbase.filter.KeyOnlyFilter;
import org.apache.hadoop.hbase.filter.PageFilter;
@@ -265,6 +266,8 @@ public class HbaseObjectWritable impleme
//java.lang.reflect.Array is a placeholder for arrays not defined above
GENERIC_ARRAY_CODE = code++;
addToMap(Array.class, GENERIC_ARRAY_CODE);
+
+ addToMap(FuzzyRowFilter.class, code++);
// make sure that this is the last statement in this static block
NEXT_CLASS_CODE = code;
Added: hbase/branches/0.94/src/test/java/org/apache/hadoop/hbase/filter/TestFuzzyRowFilter.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.94/src/test/java/org/apache/hadoop/hbase/filter/TestFuzzyRowFilter.java?rev=1438114&view=auto
==============================================================================
--- hbase/branches/0.94/src/test/java/org/apache/hadoop/hbase/filter/TestFuzzyRowFilter.java (added)
+++ hbase/branches/0.94/src/test/java/org/apache/hadoop/hbase/filter/TestFuzzyRowFilter.java Thu Jan 24 18:13:55 2013
@@ -0,0 +1,204 @@
+/**
+ * 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 org.apache.hadoop.hbase.SmallTests;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+@Category(SmallTests.class)
+public class TestFuzzyRowFilter {
+ @Test
+ public void testSatisfies() {
+ Assert.assertEquals(FuzzyRowFilter.SatisfiesCode.NEXT_EXISTS,
+ FuzzyRowFilter.satisfies(new byte[]{1, (byte) -128, 0, 0, 1}, // row to check
+ new byte[]{1, 0, 1}, // fuzzy row
+ new byte[]{0, 1, 0})); // mask
+
+ Assert.assertEquals(FuzzyRowFilter.SatisfiesCode.YES,
+ FuzzyRowFilter.satisfies(new byte[]{1, (byte) -128, 1, 0, 1},
+ new byte[]{1, 0, 1},
+ new byte[]{0, 1, 0}));
+
+ Assert.assertEquals(FuzzyRowFilter.SatisfiesCode.NEXT_EXISTS,
+ FuzzyRowFilter.satisfies(new byte[]{1, (byte) -128, 2, 0, 1},
+ new byte[]{1, 0, 1},
+ new byte[]{0, 1, 0}));
+
+ Assert.assertEquals(FuzzyRowFilter.SatisfiesCode.NO_NEXT,
+ FuzzyRowFilter.satisfies(new byte[]{2, 3, 1, 1, 1},
+ new byte[]{1, 0, 1},
+ new byte[]{0, 1, 0}));
+
+ Assert.assertEquals(FuzzyRowFilter.SatisfiesCode.YES,
+ FuzzyRowFilter.satisfies(new byte[]{1, 2, 1, 3, 3},
+ new byte[]{1, 2, 0, 3},
+ new byte[]{0, 0, 1, 0}));
+
+ Assert.assertEquals(FuzzyRowFilter.SatisfiesCode.NEXT_EXISTS,
+ FuzzyRowFilter.satisfies(new byte[]{1, 1, 1, 3, 0}, // row to check
+ new byte[]{1, 2, 0, 3}, // fuzzy row
+ new byte[]{0, 0, 1, 0})); // mask
+
+ Assert.assertEquals(FuzzyRowFilter.SatisfiesCode.NEXT_EXISTS,
+ FuzzyRowFilter.satisfies(new byte[]{1, 1, 1, 3, 0},
+ new byte[]{1, (byte) 245, 0, 3},
+ new byte[]{0, 0, 1, 0}));
+
+ Assert.assertEquals(FuzzyRowFilter.SatisfiesCode.NO_NEXT,
+ FuzzyRowFilter.satisfies(new byte[]{1, (byte) 245, 1, 3, 0},
+ new byte[]{1, 1, 0, 3},
+ new byte[]{0, 0, 1, 0}));
+
+ Assert.assertEquals(FuzzyRowFilter.SatisfiesCode.NO_NEXT,
+ FuzzyRowFilter.satisfies(new byte[]{1, 3, 1, 3, 0},
+ new byte[]{1, 2, 0, 3},
+ new byte[]{0, 0, 1, 0}));
+
+ Assert.assertEquals(FuzzyRowFilter.SatisfiesCode.NO_NEXT,
+ FuzzyRowFilter.satisfies(new byte[]{2, 1, 1, 1, 0},
+ new byte[]{1, 2, 0, 3},
+ new byte[]{0, 0, 1, 0}));
+
+ Assert.assertEquals(FuzzyRowFilter.SatisfiesCode.NEXT_EXISTS,
+ FuzzyRowFilter.satisfies(new byte[]{1, 2, 1, 0, 1},
+ new byte[]{0, 1, 2},
+ new byte[]{1, 0, 0}));
+ }
+
+ @Test
+ public void testGetNextForFuzzyRule() {
+ assertNext(
+ new byte[]{0, 1, 2}, // fuzzy row
+ new byte[]{1, 0, 0}, // mask
+ new byte[]{1, 2, 1, 0, 1}, // current
+ new byte[]{2, 1, 2, 0, 0}); // expected next
+
+ assertNext(
+ new byte[]{0, 1, 2}, // fuzzy row
+ new byte[]{1, 0, 0}, // mask
+ new byte[]{1, 1, 2, 0, 1}, // current
+ new byte[]{1, 1, 2, 0, 2}); // expected next
+
+ assertNext(
+ new byte[]{0, 1, 0, 2, 0}, // fuzzy row
+ new byte[]{1, 0, 1, 0, 1}, // mask
+ new byte[]{1, 0, 2, 0, 1}, // current
+ new byte[]{1, 1, 0, 2, 0}); // expected next
+
+ assertNext(
+ new byte[]{1, 0, 1},
+ new byte[]{0, 1, 0},
+ new byte[]{1, (byte) 128, 2, 0, 1},
+ new byte[]{1, (byte) 129, 1, 0, 0});
+
+ assertNext(
+ new byte[]{0, 1, 0, 1},
+ new byte[]{1, 0, 1, 0},
+ new byte[]{5, 1, 0, 1},
+ new byte[]{5, 1, 1, 1});
+
+ assertNext(
+ new byte[]{0, 1, 0, 1},
+ new byte[]{1, 0, 1, 0},
+ new byte[]{5, 1, 0, 1, 1},
+ new byte[]{5, 1, 0, 1, 2});
+
+ assertNext(
+ new byte[]{0, 1, 0, 0}, // fuzzy row
+ new byte[]{1, 0, 1, 1}, // mask
+ new byte[]{5, 1, (byte) 255, 1}, // current
+ new byte[]{5, 1, (byte) 255, 2}); // expected next
+
+ assertNext(
+ new byte[]{0, 1, 0, 1}, // fuzzy row
+ new byte[]{1, 0, 1, 0}, // mask
+ new byte[]{5, 1, (byte) 255, 1}, // current
+ new byte[]{6, 1, 0, 1}); // expected next
+
+ assertNext(
+ new byte[]{0, 1, 0, 1}, // fuzzy row
+ new byte[]{1, 0, 1, 0}, // mask
+ new byte[]{5, 1, (byte) 255, 0}, // current
+ new byte[]{5, 1, (byte) 255, 1}); // expected next
+
+ assertNext(
+ new byte[]{5, 1, 1, 0},
+ new byte[]{0, 0, 1, 1},
+ new byte[]{5, 1, (byte) 255, 1},
+ new byte[]{5, 1, (byte) 255, 2});
+
+ assertNext(
+ new byte[]{1, 1, 1, 1},
+ new byte[]{0, 0, 1, 1},
+ new byte[]{1, 1, 2, 2},
+ new byte[]{1, 1, 2, 3});
+
+ assertNext(
+ new byte[]{1, 1, 1, 1},
+ new byte[]{0, 0, 1, 1},
+ new byte[]{1, 1, 3, 2},
+ new byte[]{1, 1, 3, 3});
+
+ assertNext(
+ new byte[]{1, 1, 1, 1},
+ new byte[]{1, 1, 1, 1},
+ new byte[]{1, 1, 2, 3},
+ new byte[]{1, 1, 2, 4});
+
+ assertNext(
+ new byte[]{1, 1, 1, 1},
+ new byte[]{1, 1, 1, 1},
+ new byte[]{1, 1, 3, 2},
+ new byte[]{1, 1, 3, 3});
+
+ assertNext(
+ new byte[]{1, 1, 0, 0},
+ new byte[]{0, 0, 1, 1},
+ new byte[]{0, 1, 3, 2},
+ new byte[]{1, 1, 0, 0});
+
+ // No next for this one
+ Assert.assertNull(FuzzyRowFilter.getNextForFuzzyRule(
+ new byte[]{2, 3, 1, 1, 1}, // row to check
+ new byte[]{1, 0, 1}, // fuzzy row
+ new byte[]{0, 1, 0})); // mask
+ Assert.assertNull(FuzzyRowFilter.getNextForFuzzyRule(
+ new byte[]{1, (byte) 245, 1, 3, 0},
+ new byte[]{1, 1, 0, 3},
+ new byte[]{0, 0, 1, 0}));
+ Assert.assertNull(FuzzyRowFilter.getNextForFuzzyRule(
+ new byte[]{1, 3, 1, 3, 0},
+ new byte[]{1, 2, 0, 3},
+ new byte[]{0, 0, 1, 0}));
+ Assert.assertNull(FuzzyRowFilter.getNextForFuzzyRule(
+ new byte[]{2, 1, 1, 1, 0},
+ new byte[]{1, 2, 0, 3},
+ new byte[]{0, 0, 1, 0}));
+ }
+
+ private void assertNext(byte[] fuzzyRow, byte[] mask, byte[] current, byte[] expected) {
+ byte[] nextForFuzzyRule = FuzzyRowFilter.getNextForFuzzyRule(current, fuzzyRow, mask);
+ Assert.assertArrayEquals(expected, nextForFuzzyRule);
+ }
+
+ @org.junit.Rule
+ public org.apache.hadoop.hbase.ResourceCheckerJUnitRule cu =
+ new org.apache.hadoop.hbase.ResourceCheckerJUnitRule();
+}
Modified: hbase/branches/0.94/src/test/java/org/apache/hadoop/hbase/io/TestHbaseObjectWritable.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.94/src/test/java/org/apache/hadoop/hbase/io/TestHbaseObjectWritable.java?rev=1438114&r1=1438113&r2=1438114&view=diff
==============================================================================
--- hbase/branches/0.94/src/test/java/org/apache/hadoop/hbase/io/TestHbaseObjectWritable.java (original)
+++ hbase/branches/0.94/src/test/java/org/apache/hadoop/hbase/io/TestHbaseObjectWritable.java Thu Jan 24 18:13:55 2013
@@ -539,7 +539,7 @@ public class TestHbaseObjectWritable ext
* note on the test above.
*/
public void testGetNextObjectCode(){
- assertEquals(82,HbaseObjectWritable.getNextClassCode());
+ assertEquals(83,HbaseObjectWritable.getNextClassCode());
}
@org.junit.Rule