HBASE-15676 FuzzyRowFilter fails and matches all the rows in the table if the mask consists of all 0s (Matt Warhaftig)

This commit is contained in:
tedyu 2016-04-27 21:00:11 -07:00
parent e8b37422c3
commit 9343ef438f
2 changed files with 53 additions and 6 deletions

View File

@ -87,7 +87,7 @@ public class FuzzyRowFilter extends FilterBase {
.getSecond())); .getSecond()));
throw new IllegalArgumentException("Fuzzy pair lengths do not match: " + readable); 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())); p.setSecond(preprocessMask(p.getSecond()));
preprocessSearchKey(p); preprocessSearchKey(p);
} }
@ -104,12 +104,14 @@ public class FuzzyRowFilter extends FilterBase {
byte[] mask = p.getSecond(); byte[] mask = p.getSecond();
for (int i = 0; i < mask.length; i++) { for (int i = 0; i < mask.length; i++) {
// set non-fixed part of a search key to 0. // 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 * fixed positions
* @param mask * @param mask
* @return mask array * @return mask array
@ -124,7 +126,7 @@ public class FuzzyRowFilter extends FilterBase {
if (mask[i] == 0) { if (mask[i] == 0) {
mask[i] = -1; // 0 -> -1 mask[i] = -1; // 0 -> -1
} else if (mask[i] == 1) { } else if (mask[i] == 1) {
mask[i] = 0;// 1 -> 0 mask[i] = 2;// 1 -> 2
} }
} }
return mask; return mask;
@ -132,7 +134,7 @@ public class FuzzyRowFilter extends FilterBase {
private boolean isPreprocessedMask(byte[] mask) { private boolean isPreprocessedMask(byte[] mask) {
for (int i = 0; i < mask.length; i++) { for (int i = 0; i < mask.length; i++) {
if (mask[i] != -1 && mask[i] != 0) { if (mask[i] != -1 && mask[i] != 2) {
return false; return false;
} }
} }
@ -146,6 +148,10 @@ public class FuzzyRowFilter extends FilterBase {
for (int i = startIndex; i < size + startIndex; i++) { for (int i = startIndex; i < size + startIndex; i++) {
final int index = i % size; final int index = i % size;
Pair<byte[], byte[]> fuzzyData = fuzzyKeysData.get(index); Pair<byte[], byte[]> 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 = SatisfiesCode satisfiesCode =
satisfies(isReversed(), c.getRowArray(), c.getRowOffset(), c.getRowLength(), satisfies(isReversed(), c.getRowArray(), c.getRowOffset(), c.getRowLength(),
fuzzyData.getFirst(), fuzzyData.getSecond()); fuzzyData.getFirst(), fuzzyData.getSecond());

View File

@ -110,6 +110,47 @@ public class TestFuzzyRowFilterEndToEnd {
// Nothing to do. // Nothing to do.
} }
// 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<Pair<byte[], byte[]>> data = new ArrayList<Pair<byte[], byte[]>>();
byte[] fuzzyKey = Bytes.toBytesBinary("\\x9B\\x00\\x044e");
byte[] mask = new byte[] { 0, 0, 0, 0, 0 };
data.add(new Pair<byte[], byte[]>(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 @Test
public void testHBASE14782() throws IOException public void testHBASE14782() throws IOException
{ {