You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by en...@apache.org on 2013/05/10 07:58:17 UTC
svn commit: r1480887 - in /hbase/branches/0.94/src:
main/java/org/apache/hadoop/hbase/client/coprocessor/
main/java/org/apache/hadoop/hbase/filter/
test/java/org/apache/hadoop/hbase/filter/
test/java/org/apache/hadoop/hbase/zookeeper/
Author: enis
Date: Fri May 10 05:58:16 2013
New Revision: 1480887
URL: http://svn.apache.org/r1480887
Log:
HBASE-8513 [0.94] Fix class files with CRLF endings
Modified:
hbase/branches/0.94/src/main/java/org/apache/hadoop/hbase/client/coprocessor/BigDecimalColumnInterpreter.java
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
hbase/branches/0.94/src/test/java/org/apache/hadoop/hbase/zookeeper/TestRecoverableZooKeeper.java
Modified: hbase/branches/0.94/src/main/java/org/apache/hadoop/hbase/client/coprocessor/BigDecimalColumnInterpreter.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.94/src/main/java/org/apache/hadoop/hbase/client/coprocessor/BigDecimalColumnInterpreter.java?rev=1480887&r1=1480886&r2=1480887&view=diff
==============================================================================
--- hbase/branches/0.94/src/main/java/org/apache/hadoop/hbase/client/coprocessor/BigDecimalColumnInterpreter.java (original)
+++ hbase/branches/0.94/src/main/java/org/apache/hadoop/hbase/client/coprocessor/BigDecimalColumnInterpreter.java Fri May 10 05:58:16 2013
@@ -1,104 +1,104 @@
-/*
- *
- * 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.client.coprocessor;
-
-import java.io.DataInput;
-import java.io.DataOutput;
-import java.io.IOException;
-import java.math.BigDecimal;
-import java.math.RoundingMode;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.hadoop.hbase.KeyValue;
-import org.apache.hadoop.hbase.coprocessor.ColumnInterpreter;
-import org.apache.hadoop.hbase.util.Bytes;
-
-/**
- * ColumnInterpreter for doing Aggregation's with BigDecimal columns.
- * This class is required at the RegionServer also.
- *
- */
-public class BigDecimalColumnInterpreter implements ColumnInterpreter<BigDecimal, BigDecimal> {
- private static final Log log = LogFactory.getLog(BigDecimalColumnInterpreter.class);
-
- @Override
- public void readFields(DataInput arg0) throws IOException {
- }
-
- @Override
- public void write(DataOutput arg0) throws IOException {
- }
-
- @Override
- public BigDecimal getValue(byte[] family, byte[] qualifier, KeyValue kv)
- throws IOException {
- if ((kv == null || kv.getValue() == null)) return null;
- return Bytes.toBigDecimal(kv.getValue()).setScale(2, RoundingMode.HALF_EVEN);
- }
-
- @Override
- public BigDecimal add(BigDecimal val1, BigDecimal val2) {
- if ((((val1 == null) ? 1 : 0) ^ ((val2 == null) ? 1 : 0)) != 0) {
- return ((val1 == null) ? val2 : val1);
- }
- if (val1 == null) return null;
- return val1.add(val2).setScale(2, RoundingMode.HALF_EVEN);
- }
-
- @Override
- public BigDecimal getMaxValue() {
- return BigDecimal.valueOf(Double.MAX_VALUE);
- }
-
- @Override
- public BigDecimal getMinValue() {
- return BigDecimal.valueOf(Double.MIN_VALUE);
- }
-
- @Override
- public BigDecimal multiply(BigDecimal val1, BigDecimal val2) {
- return (((val1 == null) || (val2 == null)) ? null : val1.multiply(val2).setScale(2,
- RoundingMode.HALF_EVEN));
- }
-
- @Override
- public BigDecimal increment(BigDecimal val) {
- return ((val == null) ? null : val.add(BigDecimal.ONE));
- }
-
- @Override
- public BigDecimal castToReturnType(BigDecimal val) {
- return val;
- }
-
- @Override
- public int compare(BigDecimal val1, BigDecimal val2) {
- if ((((val1 == null) ? 1 : 0) ^ ((val2 == null) ? 1 : 0)) != 0) {
- return ((val1 == null) ? -1 : 1);
- }
- if (val1 == null) return 0;
- return val1.compareTo(val2);
- }
-
- @Override
- public double divideForAvg(BigDecimal val1, Long paramLong) {
- return (((paramLong == null) || (val1 == null)) ? (Double.NaN) :
- val1.doubleValue() / paramLong.doubleValue());
- }
-}
+/*
+ *
+ * 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.client.coprocessor;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.hbase.KeyValue;
+import org.apache.hadoop.hbase.coprocessor.ColumnInterpreter;
+import org.apache.hadoop.hbase.util.Bytes;
+
+/**
+ * ColumnInterpreter for doing Aggregation's with BigDecimal columns.
+ * This class is required at the RegionServer also.
+ *
+ */
+public class BigDecimalColumnInterpreter implements ColumnInterpreter<BigDecimal, BigDecimal> {
+ private static final Log log = LogFactory.getLog(BigDecimalColumnInterpreter.class);
+
+ @Override
+ public void readFields(DataInput arg0) throws IOException {
+ }
+
+ @Override
+ public void write(DataOutput arg0) throws IOException {
+ }
+
+ @Override
+ public BigDecimal getValue(byte[] family, byte[] qualifier, KeyValue kv)
+ throws IOException {
+ if ((kv == null || kv.getValue() == null)) return null;
+ return Bytes.toBigDecimal(kv.getValue()).setScale(2, RoundingMode.HALF_EVEN);
+ }
+
+ @Override
+ public BigDecimal add(BigDecimal val1, BigDecimal val2) {
+ if ((((val1 == null) ? 1 : 0) ^ ((val2 == null) ? 1 : 0)) != 0) {
+ return ((val1 == null) ? val2 : val1);
+ }
+ if (val1 == null) return null;
+ return val1.add(val2).setScale(2, RoundingMode.HALF_EVEN);
+ }
+
+ @Override
+ public BigDecimal getMaxValue() {
+ return BigDecimal.valueOf(Double.MAX_VALUE);
+ }
+
+ @Override
+ public BigDecimal getMinValue() {
+ return BigDecimal.valueOf(Double.MIN_VALUE);
+ }
+
+ @Override
+ public BigDecimal multiply(BigDecimal val1, BigDecimal val2) {
+ return (((val1 == null) || (val2 == null)) ? null : val1.multiply(val2).setScale(2,
+ RoundingMode.HALF_EVEN));
+ }
+
+ @Override
+ public BigDecimal increment(BigDecimal val) {
+ return ((val == null) ? null : val.add(BigDecimal.ONE));
+ }
+
+ @Override
+ public BigDecimal castToReturnType(BigDecimal val) {
+ return val;
+ }
+
+ @Override
+ public int compare(BigDecimal val1, BigDecimal val2) {
+ if ((((val1 == null) ? 1 : 0) ^ ((val2 == null) ? 1 : 0)) != 0) {
+ return ((val1 == null) ? -1 : 1);
+ }
+ if (val1 == null) return 0;
+ return val1.compareTo(val2);
+ }
+
+ @Override
+ public double divideForAvg(BigDecimal val1, Long paramLong) {
+ return (((paramLong == null) || (val1 == null)) ? (Double.NaN) :
+ val1.doubleValue() / paramLong.doubleValue());
+ }
+}
Modified: 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=1480887&r1=1480886&r2=1480887&view=diff
==============================================================================
--- hbase/branches/0.94/src/main/java/org/apache/hadoop/hbase/filter/FuzzyRowFilter.java (original)
+++ hbase/branches/0.94/src/main/java/org/apache/hadoop/hbase/filter/FuzzyRowFilter.java Fri May 10 05:58:16 2013
@@ -1,289 +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;
- }
-}
+/**
+ * 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/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=1480887&r1=1480886&r2=1480887&view=diff
==============================================================================
--- hbase/branches/0.94/src/test/java/org/apache/hadoop/hbase/filter/TestFuzzyRowFilter.java (original)
+++ hbase/branches/0.94/src/test/java/org/apache/hadoop/hbase/filter/TestFuzzyRowFilter.java Fri May 10 05:58:16 2013
@@ -1,204 +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();
-}
+/**
+ * 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/zookeeper/TestRecoverableZooKeeper.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.94/src/test/java/org/apache/hadoop/hbase/zookeeper/TestRecoverableZooKeeper.java?rev=1480887&r1=1480886&r2=1480887&view=diff
==============================================================================
--- hbase/branches/0.94/src/test/java/org/apache/hadoop/hbase/zookeeper/TestRecoverableZooKeeper.java (original)
+++ hbase/branches/0.94/src/test/java/org/apache/hadoop/hbase/zookeeper/TestRecoverableZooKeeper.java Fri May 10 05:58:16 2013
@@ -1,123 +1,123 @@
-/*
- * 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.zookeeper;
-
-import static org.junit.Assert.assertTrue;
-
-import java.io.IOException;
-import java.lang.reflect.Field;
-import java.util.Properties;
-
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.hbase.Abortable;
-import org.apache.hadoop.hbase.HBaseTestingUtility;
-import org.apache.hadoop.hbase.HConstants;
-import org.apache.hadoop.hbase.MediumTests;
-import org.apache.hadoop.hbase.util.Bytes;
-import org.apache.zookeeper.CreateMode;
-import org.apache.zookeeper.KeeperException;
-import org.apache.zookeeper.Watcher;
-import org.apache.zookeeper.ZooDefs.Ids;
-import org.apache.zookeeper.ZooKeeper;
-import org.apache.zookeeper.data.Stat;
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-
-@Category(MediumTests.class)
-public class TestRecoverableZooKeeper {
-
- private final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
-
- Abortable abortable = new Abortable() {
- @Override
- public void abort(String why, Throwable e) {
-
- }
-
- @Override
- public boolean isAborted() {
- return false;
- }
- };
-
- @BeforeClass
- public static void setUpBeforeClass() throws Exception {
- TEST_UTIL.startMiniZKCluster();
- }
-
- @AfterClass
- public static void tearDownAfterClass() throws Exception {
- TEST_UTIL.shutdownMiniZKCluster();
- }
-
- @Test
- public void testSetDataVersionMismatchInLoop() throws Exception {
- String znode = "/hbase/unassigned/9af7cfc9b15910a0b3d714bf40a3248f";
- Configuration conf = TEST_UTIL.getConfiguration();
- Properties properties = ZKConfig.makeZKProps(conf);
- ZooKeeperWatcher zkw = new ZooKeeperWatcher(conf, "testSetDataVersionMismatchInLoop",
- abortable, true);
- String ensemble = ZKConfig.getZKQuorumServersString(properties);
- RecoverableZooKeeper rzk = ZKUtil.connect(conf, ensemble, zkw);
- rzk.create(znode, new byte[0], Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
- rzk.setData(znode, "OPENING".getBytes(), 0);
- Field zkField = RecoverableZooKeeper.class.getDeclaredField("zk");
- zkField.setAccessible(true);
- int timeout = conf.getInt(HConstants.ZK_SESSION_TIMEOUT, HConstants.DEFAULT_ZK_SESSION_TIMEOUT);
- ZookeeperStub zkStub = new ZookeeperStub(ensemble, timeout, zkw);
- zkStub.setThrowExceptionInNumOperations(1);
- zkField.set(rzk, zkStub);
- byte[] opened = "OPENED".getBytes();
- rzk.setData(znode, opened, 1);
- byte[] data = rzk.getData(znode, false, new Stat());
- assertTrue(Bytes.equals(opened, data));
- }
-
- class ZookeeperStub extends ZooKeeper {
-
- private int throwExceptionInNumOperations;
-
- public ZookeeperStub(String connectString, int sessionTimeout, Watcher watcher)
- throws IOException {
- super(connectString, sessionTimeout, watcher);
- }
-
- public void setThrowExceptionInNumOperations(int throwExceptionInNumOperations) {
- this.throwExceptionInNumOperations = throwExceptionInNumOperations;
- }
-
- private void checkThrowKeeperException() throws KeeperException {
- if (throwExceptionInNumOperations == 1) {
- throwExceptionInNumOperations = 0;
- throw new KeeperException.ConnectionLossException();
- }
- if (throwExceptionInNumOperations > 0)
- throwExceptionInNumOperations--;
- }
-
- @Override
- public Stat setData(String path, byte[] data, int version) throws KeeperException,
- InterruptedException {
- Stat stat = super.setData(path, data, version);
- checkThrowKeeperException();
- return stat;
- }
- }
-}
+/*
+ * 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.zookeeper;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.util.Properties;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hbase.Abortable;
+import org.apache.hadoop.hbase.HBaseTestingUtility;
+import org.apache.hadoop.hbase.HConstants;
+import org.apache.hadoop.hbase.MediumTests;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.zookeeper.CreateMode;
+import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.Watcher;
+import org.apache.zookeeper.ZooDefs.Ids;
+import org.apache.zookeeper.ZooKeeper;
+import org.apache.zookeeper.data.Stat;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+@Category(MediumTests.class)
+public class TestRecoverableZooKeeper {
+
+ private final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
+
+ Abortable abortable = new Abortable() {
+ @Override
+ public void abort(String why, Throwable e) {
+
+ }
+
+ @Override
+ public boolean isAborted() {
+ return false;
+ }
+ };
+
+ @BeforeClass
+ public static void setUpBeforeClass() throws Exception {
+ TEST_UTIL.startMiniZKCluster();
+ }
+
+ @AfterClass
+ public static void tearDownAfterClass() throws Exception {
+ TEST_UTIL.shutdownMiniZKCluster();
+ }
+
+ @Test
+ public void testSetDataVersionMismatchInLoop() throws Exception {
+ String znode = "/hbase/unassigned/9af7cfc9b15910a0b3d714bf40a3248f";
+ Configuration conf = TEST_UTIL.getConfiguration();
+ Properties properties = ZKConfig.makeZKProps(conf);
+ ZooKeeperWatcher zkw = new ZooKeeperWatcher(conf, "testSetDataVersionMismatchInLoop",
+ abortable, true);
+ String ensemble = ZKConfig.getZKQuorumServersString(properties);
+ RecoverableZooKeeper rzk = ZKUtil.connect(conf, ensemble, zkw);
+ rzk.create(znode, new byte[0], Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
+ rzk.setData(znode, "OPENING".getBytes(), 0);
+ Field zkField = RecoverableZooKeeper.class.getDeclaredField("zk");
+ zkField.setAccessible(true);
+ int timeout = conf.getInt(HConstants.ZK_SESSION_TIMEOUT, HConstants.DEFAULT_ZK_SESSION_TIMEOUT);
+ ZookeeperStub zkStub = new ZookeeperStub(ensemble, timeout, zkw);
+ zkStub.setThrowExceptionInNumOperations(1);
+ zkField.set(rzk, zkStub);
+ byte[] opened = "OPENED".getBytes();
+ rzk.setData(znode, opened, 1);
+ byte[] data = rzk.getData(znode, false, new Stat());
+ assertTrue(Bytes.equals(opened, data));
+ }
+
+ class ZookeeperStub extends ZooKeeper {
+
+ private int throwExceptionInNumOperations;
+
+ public ZookeeperStub(String connectString, int sessionTimeout, Watcher watcher)
+ throws IOException {
+ super(connectString, sessionTimeout, watcher);
+ }
+
+ public void setThrowExceptionInNumOperations(int throwExceptionInNumOperations) {
+ this.throwExceptionInNumOperations = throwExceptionInNumOperations;
+ }
+
+ private void checkThrowKeeperException() throws KeeperException {
+ if (throwExceptionInNumOperations == 1) {
+ throwExceptionInNumOperations = 0;
+ throw new KeeperException.ConnectionLossException();
+ }
+ if (throwExceptionInNumOperations > 0)
+ throwExceptionInNumOperations--;
+ }
+
+ @Override
+ public Stat setData(String path, byte[] data, int version) throws KeeperException,
+ InterruptedException {
+ Stat stat = super.setData(path, data, version);
+ checkThrowKeeperException();
+ return stat;
+ }
+ }
+}