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; + } + } +}