From 4f2d8dc328ec1e722ae6a78cb7416b171ede9ebd Mon Sep 17 00:00:00 2001 From: tedyu Date: Wed, 27 Apr 2016 21:03:34 -0700 Subject: [PATCH] HBASE-15676 FuzzyRowFilter fails and matches all the rows in the table if the mask consists of all 0s (Matt Warhaftig) --- .../hadoop/hbase/filter/FuzzyRowFilter.java | 16 ++++--- .../filter/TestFuzzyRowFilterEndToEnd.java | 43 ++++++++++++++++++- 2 files changed, 53 insertions(+), 6 deletions(-) diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/filter/FuzzyRowFilter.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/filter/FuzzyRowFilter.java index c3290f6d7be..838e4bda7b6 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/filter/FuzzyRowFilter.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/filter/FuzzyRowFilter.java @@ -86,7 +86,7 @@ public class FuzzyRowFilter extends FilterBase { .getSecond())); throw new IllegalArgumentException("Fuzzy pair lengths do not match: " + readable); } - // update mask ( 0 -> -1 (0xff), 1 -> 0) + // update mask ( 0 -> -1 (0xff), 1 -> 2) p.setSecond(preprocessMask(p.getSecond())); preprocessSearchKey(p); } @@ -102,12 +102,14 @@ public class FuzzyRowFilter extends FilterBase { byte[] mask = p.getSecond(); for (int i = 0; i < mask.length; i++) { // set non-fixed part of a search key to 0. - if (mask[i] == 0) key[i] = 0; + if (mask[i] == 2) { + key[i] = 0; + } } } /** - * We need to preprocess mask array, as since we treat 0's as unfixed positions and -1 (0xff) as + * We need to preprocess mask array, as since we treat 2's as unfixed positions and -1 (0xff) as * fixed positions * @param mask * @return mask array @@ -121,7 +123,7 @@ public class FuzzyRowFilter extends FilterBase { if (mask[i] == 0) { mask[i] = -1; // 0 -> -1 } else if (mask[i] == 1) { - mask[i] = 0;// 1 -> 0 + mask[i] = 2;// 1 -> 2 } } return mask; @@ -129,7 +131,7 @@ public class FuzzyRowFilter extends FilterBase { private boolean isPreprocessedMask(byte[] mask) { for (int i = 0; i < mask.length; i++) { - if (mask[i] != -1 && mask[i] != 0) { + if (mask[i] != -1 && mask[i] != 2) { return false; } } @@ -143,6 +145,10 @@ public class FuzzyRowFilter extends FilterBase { for (int i = startIndex; i < size + startIndex; i++) { final int index = i % size; Pair fuzzyData = fuzzyKeysData.get(index); + // This shift is idempotent - always end up with 0 and -1 as mask values. + for (int j = 0; j < fuzzyData.getSecond().length; j++) { + fuzzyData.getSecond()[j] >>= 2; + } SatisfiesCode satisfiesCode = satisfies(isReversed(), c.getRowArray(), c.getRowOffset(), c.getRowLength(), fuzzyData.getFirst(), fuzzyData.getSecond()); diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/filter/TestFuzzyRowFilterEndToEnd.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/filter/TestFuzzyRowFilterEndToEnd.java index 91795495371..fa738b2931e 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/filter/TestFuzzyRowFilterEndToEnd.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/filter/TestFuzzyRowFilterEndToEnd.java @@ -110,7 +110,48 @@ public class TestFuzzyRowFilterEndToEnd { // Nothing to do. } - @Test + // HBASE-15676 Test that fuzzy info of all fixed bits (0s) finds matching row. + @Test + public void testAllFixedBits() throws IOException { + String cf = "f"; + String cq = "q"; + String table = "testAllFixedBits"; + + Table ht = + TEST_UTIL.createTable(TableName.valueOf(table), Bytes.toBytes(cf), Integer.MAX_VALUE); + // Load data + String[] rows = new String[] { "\\x9C\\x00\\x044\\x00\\x00\\x00\\x00", + "\\x9C\\x00\\x044\\x01\\x00\\x00\\x00", "\\x9C\\x00\\x044\\x00\\x01\\x00\\x00", + "\\x9B\\x00\\x044e\\x9B\\x02\\xBB", "\\x9C\\x00\\x044\\x00\\x00\\x01\\x00", + "\\x9C\\x00\\x044\\x00\\x01\\x00\\x01", "\\x9B\\x00\\x044e\\xBB\\xB2\\xBB", }; + + for (int i = 0; i < rows.length; i++) { + Put p = new Put(Bytes.toBytesBinary(rows[i])); + p.addColumn(cf.getBytes(), cq.getBytes(), "value".getBytes()); + ht.put(p); + } + + TEST_UTIL.flush(); + + List> data = new ArrayList>(); + byte[] fuzzyKey = Bytes.toBytesBinary("\\x9B\\x00\\x044e"); + byte[] mask = new byte[] { 0, 0, 0, 0, 0 }; + data.add(new Pair(fuzzyKey, mask)); + FuzzyRowFilter filter = new FuzzyRowFilter(data); + + Scan scan = new Scan(); + scan.setFilter(filter); + + ResultScanner scanner = ht.getScanner(scan); + int total = 0; + while (scanner.next() != null) { + total++; + } + assertEquals(2, total); + TEST_UTIL.deleteTable(TableName.valueOf(table)); + } + + @Test public void testHBASE14782() throws IOException { String cf = "f";