Repository: phoenix Updated Branches: refs/heads/4.0 856c6bc5d -> 069b4f611
PHOENIX-1472 Fix salt bucket for Integer.MIN_VALUE Calculate the correct salt bucket when the hash code of a row key's contents is equal to Integer.MIN_VALUE. Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/069b4f61 Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/069b4f61 Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/069b4f61 Branch: refs/heads/4.0 Commit: 069b4f611ce40dc41c70358180b25568434cf886 Parents: 856c6bc Author: Gabriel Reid <gabri...@ngdata.com> Authored: Thu Nov 20 16:13:45 2014 +0100 Committer: Gabriel Reid <gabri...@ngdata.com> Committed: Wed Nov 26 20:33:42 2014 +0100 ---------------------------------------------------------------------- .../org/apache/phoenix/schema/SaltingUtil.java | 5 +- .../apache/phoenix/schema/SaltingUtilTest.java | 55 ++++++++++++++++++++ 2 files changed, 57 insertions(+), 3 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/phoenix/blob/069b4f61/phoenix-core/src/main/java/org/apache/phoenix/schema/SaltingUtil.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/SaltingUtil.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/SaltingUtil.java index 34a2cc0..527f4a6 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/schema/SaltingUtil.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/SaltingUtil.java @@ -73,8 +73,7 @@ public class SaltingUtil { // Generate the bucket byte given a byte array and the number of buckets. public static byte getSaltingByte(byte[] value, int offset, int length, int bucketNum) { int hash = calculateHashCode(value, offset, length); - byte bucketByte = (byte) ((Math.abs(hash) % bucketNum)); - return bucketByte; + return (byte) Math.abs(hash % bucketNum); } private static int calculateHashCode(byte a[], int offset, int length) { @@ -98,7 +97,7 @@ public class SaltingUtil { } byte[] upperRange = minMaxRange.getUpperRange(); - if(!minMaxRange.upperUnbound()) { + if(!minMaxRange.upperUnbound()) { byte[] newUpperRange = new byte[upperRange.length + 1]; newUpperRange[0] = saltByte; System.arraycopy(upperRange, 0, newUpperRange, 1, upperRange.length); http://git-wip-us.apache.org/repos/asf/phoenix/blob/069b4f61/phoenix-core/src/test/java/org/apache/phoenix/schema/SaltingUtilTest.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/test/java/org/apache/phoenix/schema/SaltingUtilTest.java b/phoenix-core/src/test/java/org/apache/phoenix/schema/SaltingUtilTest.java new file mode 100644 index 0000000..9642045 --- /dev/null +++ b/phoenix-core/src/test/java/org/apache/phoenix/schema/SaltingUtilTest.java @@ -0,0 +1,55 @@ +/* + * 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.phoenix.schema; + +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Sets; +import org.apache.hadoop.hbase.util.Bytes; +import org.junit.Test; + +import java.util.Set; + +import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; + +public class SaltingUtilTest { + + @Test + public void testGetSaltingByte() { + Set<Byte> saltBytes = Sets.newHashSet(); + for (int i = 0; i < 100; i++) { + saltBytes.add(SaltingUtil.getSaltingByte(Bytes.toBytes(i), 0, Bytes.SIZEOF_INT, 3)); + } + assertEquals(ImmutableSet.of((byte)0, (byte)1, (byte)2), saltBytes); + } + + + /** + * Check an edge case where a row key's hash code is equal to Integer.MIN_VALUE. + */ + @Test + public void testGetSaltingByte_EdgeCaseHashCode() { + // This array has a hashCode of Integer.MIN_VALUE based on the hashing in SaltingUtil + byte[] rowKey = new byte[] { -106, 0, -10, 0, 19, -2 }; + byte saltingByte = SaltingUtil.getSaltingByte(rowKey, 0, rowKey.length, 3); + + assertTrue("Salting byte should be 0 or 1 or 2 but was " + saltingByte, + ImmutableSet.of((byte)0, (byte)1, (byte)2).contains(saltingByte)); + + } +} \ No newline at end of file