Skip to content

Commit 25b34d3

Browse files
fix: fuzzy filter adapter when UNSAFE_UNALIGNED is unset (#4508)
Change-Id: I1436726178e8b5e563c28a95dcae9887361dbf7d Thank you for opening a Pull Request! Before submitting your PR, there are a few things you can do to make sure it goes smoothly: - [ ] Make sure to open an issue as a [bug/issue](https://togithub.com/googleapis/java-bigtable-hbase/issues/new/choose) before writing your code! That way we can discuss the change, evaluate designs, and agree on the general idea - [ ] Ensure the tests and linter pass - [ ] Code coverage does not decrease (if any source code was changed) - [ ] Appropriate docs were updated (if necessary) Fixes #<issue_number_goes_here> ☕️ If you write sample code, please follow the [samples format]( https://togithub.com/GoogleCloudPlatform/java-docs-samples/blob/main/SAMPLE_FORMAT.md).
1 parent 2905049 commit 25b34d3

File tree

1 file changed

+38
-6
lines changed
  • bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/adapters/filters

1 file changed

+38
-6
lines changed

bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/adapters/filters/FuzzyRowFilterAdapter.java

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,13 @@
2323
import com.google.cloud.bigtable.hbase.adapters.read.ReaderExpressionHelper;
2424
import com.google.cloud.bigtable.hbase.adapters.read.ReaderExpressionHelper.QuoteMetaOutputStream;
2525
import com.google.common.base.Preconditions;
26+
import com.google.common.collect.ImmutableList;
2627
import com.google.protobuf.ByteString;
2728
import java.io.IOException;
2829
import java.lang.reflect.Field;
30+
import java.util.Arrays;
2931
import java.util.List;
32+
import java.util.Optional;
3033
import org.apache.hadoop.hbase.filter.FuzzyRowFilter;
3134
import org.apache.hadoop.hbase.util.Pair;
3235

@@ -41,6 +44,9 @@ public class FuzzyRowFilterAdapter extends TypedFilterAdapterBase<FuzzyRowFilter
4144
private static Field FUZZY_KEY_DATA_FIELD;
4245
private static Exception FUZZY_KEY_DATA_FIELD_EXCEPTION;
4346

47+
private final Optional<String> compatProblem;
48+
private final boolean maskWillBePreprocessed;
49+
4450
static {
4551
try {
4652
FUZZY_KEY_DATA_FIELD = FuzzyRowFilter.class.getDeclaredField("fuzzyKeysData");
@@ -50,9 +56,33 @@ public class FuzzyRowFilterAdapter extends TypedFilterAdapterBase<FuzzyRowFilter
5056
}
5157
}
5258

59+
public FuzzyRowFilterAdapter() {
60+
byte[] testValue = "aa".getBytes();
61+
byte[] testMask = new byte[] {0, 1}; // literal, wildcard
62+
63+
FuzzyRowFilter testFilter =
64+
new FuzzyRowFilter(ImmutableList.of(Pair.newPair("aa".getBytes(), testMask.clone())));
65+
List<Pair<byte[], byte[]>> pairs = extractFuzzyRowFilterPairs(testFilter);
66+
if (pairs.size() != 1) {
67+
compatProblem =
68+
Optional.of(
69+
"Failed to probe FuzzyRowFilter implementation, expected 1 encoded pair, but got: "
70+
+ pairs);
71+
maskWillBePreprocessed = false;
72+
return;
73+
}
74+
Pair<byte[], byte[]> pair = pairs.get(0);
75+
maskWillBePreprocessed = !Arrays.equals(testMask, pair.getSecond());
76+
compatProblem = Optional.empty();
77+
}
78+
5379
/** {@inheritDoc} */
5480
@Override
5581
public Filter adapt(FilterAdapterContext context, FuzzyRowFilter filter) throws IOException {
82+
if (compatProblem.isPresent()) {
83+
throw new IllegalStateException(compatProblem.get());
84+
}
85+
5686
List<Pair<byte[], byte[]>> pairs = extractFuzzyRowFilterPairs(filter);
5787
if (pairs.isEmpty()) {
5888
return FILTERS.pass();
@@ -67,11 +97,13 @@ public Filter adapt(FilterAdapterContext context, FuzzyRowFilter filter) throws
6797
return interleave;
6898
}
6999

70-
private static Filter createSingleRowFilter(byte[] key, byte[] mask) throws IOException {
100+
private Filter createSingleRowFilter(byte[] key, byte[] mask) throws IOException {
71101
ByteString.Output output = ByteString.newOutput(key.length * 2);
72102
QuoteMetaOutputStream quotingStream = new QuoteMetaOutputStream(output);
73103
for (int i = 0; i < mask.length; i++) {
74-
if (mask[i] == -1) {
104+
// Handle literals: under normal circumstances (when preprocessing is available), -1 means
105+
// literal. When UnsafeAvailChecker.unaligned() is false, then mask for a literal will be 0.
106+
if (mask[i] == -1 || (!maskWillBePreprocessed && mask[i] == 0)) {
75107
quotingStream.write(key[i]);
76108
} else {
77109
// Write unquoted to match any byte at this position:
@@ -85,16 +117,16 @@ private static Filter createSingleRowFilter(byte[] key, byte[] mask) throws IOEx
85117
}
86118

87119
@SuppressWarnings("unchecked")
88-
static List<Pair<byte[], byte[]>> extractFuzzyRowFilterPairs(FuzzyRowFilter filter)
89-
throws IOException {
120+
static List<Pair<byte[], byte[]>> extractFuzzyRowFilterPairs(FuzzyRowFilter filter) {
90121
// TODO: Change FuzzyRowFilter to expose fuzzyKeysData.
91122
if (FUZZY_KEY_DATA_FIELD_EXCEPTION != null) {
92-
throw new IOException("Could not read the contents of the FuzzyRowFilter");
123+
throw new IllegalStateException(
124+
"Could not read the contents of the FuzzyRowFilter", FUZZY_KEY_DATA_FIELD_EXCEPTION);
93125
}
94126
try {
95127
return (List<Pair<byte[], byte[]>>) FUZZY_KEY_DATA_FIELD.get(filter);
96128
} catch (IllegalArgumentException | IllegalAccessException e) {
97-
throw new IOException("Could not read the contents of the FuzzyRowFilter", e);
129+
throw new IllegalStateException("Could not read the contents of the FuzzyRowFilter", e);
98130
}
99131
}
100132

0 commit comments

Comments
 (0)