You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by ra...@apache.org on 2015/05/05 08:09:04 UTC
[5/5] hbase git commit: HBASE-10800 - Use CellComparator instead of
KVComparator (Ram)
HBASE-10800 - Use CellComparator instead of KVComparator (Ram)
Project: http://git-wip-us.apache.org/repos/asf/hbase/repo
Commit: http://git-wip-us.apache.org/repos/asf/hbase/commit/977f8674
Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/977f8674
Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/977f8674
Branch: refs/heads/master
Commit: 977f867439e960c668ee6311e47c904efc40f219
Parents: 25b5098
Author: ramkrishna <ra...@gmail.com>
Authored: Tue May 5 11:38:10 2015 +0530
Committer: ramkrishna <ra...@gmail.com>
Committed: Tue May 5 11:38:10 2015 +0530
----------------------------------------------------------------------
.../org/apache/hadoop/hbase/HRegionInfo.java | 4 +-
.../apache/hadoop/hbase/client/MetaCache.java | 9 +-
.../org/apache/hadoop/hbase/client/Result.java | 11 +-
.../apache/hadoop/hbase/filter/FilterList.java | 6 +-
.../apache/hadoop/hbase/filter/ParseFilter.java | 6 +-
.../hbase/client/TestClientNoCluster.java | 4 +-
.../hadoop/hbase/client/TestOperation.java | 9 +-
.../org/apache/hadoop/hbase/CellComparator.java | 826 ++++++++++++-------
.../java/org/apache/hadoop/hbase/CellUtil.java | 146 +++-
.../java/org/apache/hadoop/hbase/KeyValue.java | 48 +-
.../apache/hadoop/hbase/KeyValueTestUtil.java | 2 +-
.../org/apache/hadoop/hbase/KeyValueUtil.java | 123 ++-
.../java/org/apache/hadoop/hbase/TableName.java | 2 +-
.../hadoop/hbase/codec/KeyValueCodec.java | 3 +-
.../hbase/codec/KeyValueCodecWithTags.java | 3 +-
.../io/encoding/BufferedDataBlockEncoder.java | 83 +-
.../io/encoding/CopyKeyDataBlockEncoder.java | 4 +-
.../hbase/io/encoding/DataBlockEncoder.java | 10 +-
.../hbase/io/encoding/DiffKeyDeltaEncoder.java | 4 +-
.../hbase/io/encoding/FastDiffDeltaEncoder.java | 4 +-
.../io/encoding/PrefixKeyDeltaEncoder.java | 4 +-
.../org/apache/hadoop/hbase/util/Bytes.java | 91 +-
.../hbase/util/test/RedundantKVGenerator.java | 3 +-
.../apache/hadoop/hbase/TestCellComparator.java | 100 +--
.../org/apache/hadoop/hbase/TestKeyValue.java | 145 +---
.../hadoop/hbase/codec/TestCellCodec.java | 7 +-
.../hbase/codec/TestCellCodecWithTags.java | 8 +-
.../hbase/codec/TestKeyValueCodecWithTags.java | 8 +-
.../org/apache/hadoop/hbase/util/TestBytes.java | 28 +-
.../apache/hadoop/hbase/types/TestPBCell.java | 3 +-
.../mapreduce/IntegrationTestImportTsv.java | 5 +-
.../hbase/codec/prefixtree/PrefixTreeCodec.java | 18 +-
.../codec/prefixtree/PrefixTreeSeeker.java | 12 +-
.../decode/PrefixTreeArrayScanner.java | 4 +-
.../codec/prefixtree/decode/PrefixTreeCell.java | 25 +-
.../codec/prefixtree/row/BaseTestRowData.java | 4 +-
.../prefixtree/row/TestPrefixTreeSearcher.java | 6 +-
.../row/data/TestRowDataNumberStrings.java | 2 +-
.../row/data/TestRowDataSearcherRowMiss.java | 14 +-
.../prefixtree/row/data/TestRowDataSimple.java | 14 +-
.../hadoop/hbase/io/HalfStoreFileReader.java | 24 +-
.../hadoop/hbase/io/hfile/FixedFileTrailer.java | 54 +-
.../org/apache/hadoop/hbase/io/hfile/HFile.java | 14 +-
.../hadoop/hbase/io/hfile/HFileBlockIndex.java | 50 +-
.../hbase/io/hfile/HFilePrettyPrinter.java | 8 +-
.../hadoop/hbase/io/hfile/HFileReaderImpl.java | 39 +-
.../hbase/io/hfile/HFileWriterFactory.java | 4 +-
.../hadoop/hbase/io/hfile/HFileWriterImpl.java | 141 +++-
.../hbase/mapreduce/HFileOutputFormat2.java | 3 +-
.../hbase/mapreduce/KeyValueSerialization.java | 5 +-
.../hbase/mapreduce/KeyValueSortReducer.java | 3 +-
.../hadoop/hbase/mapreduce/PutSortReducer.java | 3 +-
.../mapreduce/SimpleTotalOrderPartitioner.java | 2 +-
.../hadoop/hbase/mapreduce/TextSortReducer.java | 3 +-
.../hbase/regionserver/CellSkipListSet.java | 4 +-
.../hbase/regionserver/DefaultMemStore.java | 7 +-
.../hbase/regionserver/DefaultStoreEngine.java | 4 +-
.../regionserver/DefaultStoreFileManager.java | 6 +-
.../GetClosestRowBeforeTracker.java | 17 +-
.../hadoop/hbase/regionserver/HRegion.java | 10 +-
.../hbase/regionserver/HRegionFileSystem.java | 6 +-
.../hadoop/hbase/regionserver/HStore.java | 15 +-
.../hadoop/hbase/regionserver/KeyValueHeap.java | 10 +-
.../hadoop/hbase/regionserver/Region.java | 4 +-
.../regionserver/ReversedKeyValueHeap.java | 10 +-
.../regionserver/ReversedStoreScanner.java | 9 +-
.../hadoop/hbase/regionserver/ScanInfo.java | 10 +-
.../hbase/regionserver/ScanQueryMatcher.java | 40 +-
.../apache/hadoop/hbase/regionserver/Store.java | 4 +-
.../hadoop/hbase/regionserver/StoreEngine.java | 8 +-
.../hadoop/hbase/regionserver/StoreFile.java | 72 +-
.../hbase/regionserver/StoreFileScanner.java | 11 +-
.../hadoop/hbase/regionserver/StoreScanner.java | 8 +-
.../regionserver/StripeMultiFileWriter.java | 40 +-
.../hbase/regionserver/StripeStoreEngine.java | 4 +-
.../regionserver/StripeStoreFileManager.java | 16 +-
.../hbase/regionserver/wal/WALCellCodec.java | 3 +-
.../hadoop/hbase/regionserver/wal/WALEdit.java | 6 +-
.../apache/hadoop/hbase/util/BloomFilter.java | 2 +-
.../hadoop/hbase/util/BloomFilterFactory.java | 5 +-
.../hadoop/hbase/util/ByteBloomFilter.java | 6 +-
.../hbase/util/CollectionBackedScanner.java | 14 +-
.../hadoop/hbase/util/CompoundBloomFilter.java | 7 +-
.../hbase/util/CompoundBloomFilterBase.java | 5 +-
.../hbase/util/CompoundBloomFilterWriter.java | 4 +-
.../hadoop/hbase/util/CompressionTest.java | 2 +-
.../org/apache/hadoop/hbase/util/HBaseFsck.java | 5 +-
.../hadoop/hbase/HBaseTestingUtility.java | 2 +-
.../hbase/HFilePerformanceEvaluation.java | 2 +-
.../apache/hadoop/hbase/MetaMockingUtil.java | 2 +-
.../apache/hadoop/hbase/TestSerialization.java | 8 +-
.../apache/hadoop/hbase/client/TestResult.java | 17 +-
.../hbase/codec/TestCellMessageCodec.java | 7 +-
.../hbase/filter/TestDependentColumnFilter.java | 3 +-
.../apache/hadoop/hbase/filter/TestFilter.java | 9 +-
.../hadoop/hbase/filter/TestFilterList.java | 15 +-
.../TestSingleColumnValueExcludeFilter.java | 5 +-
.../hbase/io/TestHalfStoreFileReader.java | 7 +-
.../encoding/TestBufferedDataBlockEncoder.java | 33 +
.../io/encoding/TestDataBlockEncoders.java | 5 +-
.../io/encoding/TestPrefixTreeEncoding.java | 15 +-
.../encoding/TestSeekToBlockWithEncoders.java | 3 +-
.../hadoop/hbase/io/hfile/TestCacheOnWrite.java | 3 +-
.../hbase/io/hfile/TestFixedFileTrailer.java | 25 +-
.../apache/hadoop/hbase/io/hfile/TestHFile.java | 156 +++-
.../hadoop/hbase/io/hfile/TestHFileBlock.java | 3 +-
.../hbase/io/hfile/TestHFileBlockIndex.java | 24 +-
.../hadoop/hbase/io/hfile/TestHFileSeek.java | 6 +-
.../hbase/io/hfile/TestHFileWriterV2.java | 6 +-
.../hbase/io/hfile/TestHFileWriterV3.java | 9 +-
.../hadoop/hbase/io/hfile/TestPrefetch.java | 3 +-
.../hadoop/hbase/io/hfile/TestReseekTo.java | 3 +-
.../hadoop/hbase/io/hfile/TestSeekTo.java | 3 +-
.../hbase/regionserver/KeyValueScanFixture.java | 12 +-
.../hbase/regionserver/MockStoreFile.java | 4 +-
.../hbase/regionserver/TestCellSkipListSet.java | 3 +-
.../regionserver/TestCompoundBloomFilter.java | 13 +-
.../hbase/regionserver/TestDefaultMemStore.java | 14 +-
.../regionserver/TestDefaultStoreEngine.java | 4 +-
.../regionserver/TestGetClosestAtOrBefore.java | 4 +-
.../hadoop/hbase/regionserver/TestHRegion.java | 12 +-
.../hbase/regionserver/TestKeyValueHeap.java | 9 +-
.../regionserver/TestKeyValueScanFixture.java | 3 +-
.../regionserver/TestMultiColumnScanner.java | 4 +-
.../hbase/regionserver/TestQueryMatcher.java | 6 +-
.../hbase/regionserver/TestRecoveredEdits.java | 6 +-
.../regionserver/TestReversibleScanners.java | 5 +-
.../TestScannerHeartbeatMessages.java | 6 +-
.../regionserver/TestSeekOptimizations.java | 5 +-
.../hadoop/hbase/regionserver/TestStore.java | 12 +-
.../hbase/regionserver/TestStoreFile.java | 26 +-
.../hbase/regionserver/TestStoreScanner.java | 13 +-
.../hbase/regionserver/TestStripeCompactor.java | 6 +-
.../regionserver/TestStripeStoreEngine.java | 4 +-
.../TestStripeStoreFileManager.java | 5 +-
.../compactions/TestStripeCompactionPolicy.java | 3 +-
.../TestReplicationWALEntryFilters.java | 3 +-
137 files changed, 1960 insertions(+), 1131 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/hbase/blob/977f8674/hbase-client/src/main/java/org/apache/hadoop/hbase/HRegionInfo.java
----------------------------------------------------------------------
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/HRegionInfo.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/HRegionInfo.java
index ad85d5e..b127489 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/HRegionInfo.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/HRegionInfo.java
@@ -27,10 +27,10 @@ import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.hbase.KeyValue.KVComparator;
import org.apache.hadoop.hbase.classification.InterfaceAudience;
import org.apache.hadoop.hbase.classification.InterfaceStability;
import org.apache.hadoop.hbase.client.RegionReplicaUtil;
+import org.apache.hadoop.hbase.KeyValue.KVComparator;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.exceptions.DeserializationException;
import org.apache.hadoop.hbase.master.RegionState;
@@ -842,7 +842,7 @@ public class HRegionInfo implements Comparable<HRegionInfo> {
@Deprecated
public KVComparator getComparator() {
return isMetaRegion()?
- KeyValue.META_COMPARATOR: KeyValue.COMPARATOR;
+ KeyValue.META_COMPARATOR: KeyValue.COMPARATOR;
}
/**
http://git-wip-us.apache.org/repos/asf/hbase/blob/977f8674/hbase-client/src/main/java/org/apache/hadoop/hbase/client/MetaCache.java
----------------------------------------------------------------------
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/MetaCache.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/MetaCache.java
index 9cfc516..66ef546 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/MetaCache.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/MetaCache.java
@@ -31,13 +31,12 @@ import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.hbase.HConstants;
import org.apache.hadoop.hbase.HRegionInfo;
import org.apache.hadoop.hbase.HRegionLocation;
-import org.apache.hadoop.hbase.KeyValue;
import org.apache.hadoop.hbase.RegionLocations;
import org.apache.hadoop.hbase.ServerName;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.classification.InterfaceAudience;
import org.apache.hadoop.hbase.util.Bytes;
-import org.apache.hadoop.hbase.KeyValue.KVComparator;
+import org.apache.hadoop.hbase.CellComparator;
/**
* A cache implementation for region locations from meta.
@@ -96,9 +95,9 @@ public class MetaCache {
return null;
}
- private KVComparator getRowComparator(TableName tableName) {
- return TableName.META_TABLE_NAME.equals(tableName) ? KeyValue.META_COMPARATOR
- : KeyValue.COMPARATOR;
+ private CellComparator getRowComparator(TableName tableName) {
+ return TableName.META_TABLE_NAME.equals(tableName) ? CellComparator.META_COMPARATOR
+ : CellComparator.COMPARATOR;
}
/**
* Put a newly discovered HRegionLocation into the cache.
http://git-wip-us.apache.org/repos/asf/hbase/blob/977f8674/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Result.java
----------------------------------------------------------------------
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Result.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Result.java
index 5a9aff3..4c58da5 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Result.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Result.java
@@ -31,6 +31,7 @@ import java.util.NavigableMap;
import java.util.TreeMap;
import org.apache.hadoop.hbase.Cell;
+import org.apache.hadoop.hbase.CellComparator;
import org.apache.hadoop.hbase.CellScannable;
import org.apache.hadoop.hbase.CellScanner;
import org.apache.hadoop.hbase.CellUtil;
@@ -204,14 +205,14 @@ public class Result implements CellScannable, CellScanner {
* Return the array of Cells backing this Result instance.
*
* The array is sorted from smallest -> largest using the
- * {@link KeyValue#COMPARATOR}.
+ * {@link CellComparator#COMPARATOR}.
*
* The array only contains what your Get or Scan specifies and no more.
* For example if you request column "A" 1 version you will have at most 1
* Cell in the array. If you request column "A" with 2 version you will
* have at most 2 Cells, with the first one being the newer timestamp and
* the second being the older timestamp (this is the sort order defined by
- * {@link KeyValue#COMPARATOR}). If columns don't exist, they won't be
+ * {@link CellComparator#COMPARATOR}). If columns don't exist, they won't be
* present in the result. Therefore if you ask for 1 version all columns,
* it is safe to iterate over this array and expect to see 1 Cell for
* each column and no more.
@@ -237,7 +238,7 @@ public class Result implements CellScannable, CellScanner {
/**
* Return the Cells for the specific column. The Cells are sorted in
- * the {@link KeyValue#COMPARATOR} order. That implies the first entry in
+ * the {@link CellComparator#COMPARATOR} order. That implies the first entry in
* the list is the most recent column. If the query (Scan or Get) only
* requested 1 version the list will contain at most 1 entry. If the column
* did not exist in the result set (either the column does not exist
@@ -282,7 +283,7 @@ public class Result implements CellScannable, CellScanner {
family, qualifier);
// pos === ( -(insertion point) - 1)
- int pos = Arrays.binarySearch(kvs, searchTerm, KeyValue.COMPARATOR);
+ int pos = Arrays.binarySearch(kvs, searchTerm, CellComparator.COMPARATOR);
// never will exact match
if (pos < 0) {
pos = (pos+1) * -1;
@@ -327,7 +328,7 @@ public class Result implements CellScannable, CellScanner {
qualifier, qoffset, qlength);
// pos === ( -(insertion point) - 1)
- int pos = Arrays.binarySearch(kvs, searchTerm, KeyValue.COMPARATOR);
+ int pos = Arrays.binarySearch(kvs, searchTerm, CellComparator.COMPARATOR);
// never will exact match
if (pos < 0) {
pos = (pos+1) * -1;
http://git-wip-us.apache.org/repos/asf/hbase/blob/977f8674/hbase-client/src/main/java/org/apache/hadoop/hbase/filter/FilterList.java
----------------------------------------------------------------------
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/filter/FilterList.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/filter/FilterList.java
index ba1a818..a7856cd 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/filter/FilterList.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/filter/FilterList.java
@@ -25,7 +25,7 @@ import java.util.List;
import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.CellComparator;
-import org.apache.hadoop.hbase.KeyValue;
+import org.apache.hadoop.hbase.CellUtil;
import org.apache.hadoop.hbase.classification.InterfaceAudience;
import org.apache.hadoop.hbase.classification.InterfaceStability;
import org.apache.hadoop.hbase.exceptions.DeserializationException;
@@ -216,7 +216,7 @@ final public class FilterList extends Filter {
@Override
public Cell transformCell(Cell c) throws IOException {
- if (!CellComparator.equals(c, referenceCell)) {
+ if (!CellUtil.equals(c, referenceCell)) {
throw new IllegalStateException("Reference Cell: " + this.referenceCell + " does not match: "
+ c);
}
@@ -415,7 +415,7 @@ final public class FilterList extends Filter {
keyHint = curKeyHint;
continue;
}
- if (KeyValue.COMPARATOR.compare(keyHint, curKeyHint) > 0) {
+ if (CellComparator.COMPARATOR.compare(keyHint, curKeyHint) > 0) {
keyHint = curKeyHint;
}
}
http://git-wip-us.apache.org/repos/asf/hbase/blob/977f8674/hbase-client/src/main/java/org/apache/hadoop/hbase/filter/ParseFilter.java
----------------------------------------------------------------------
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/filter/ParseFilter.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/filter/ParseFilter.java
index 8101f4a..5089308 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/filter/ParseFilter.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/filter/ParseFilter.java
@@ -32,7 +32,6 @@ import java.util.Stack;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.apache.hadoop.hbase.KeyValue;
import org.apache.hadoop.hbase.classification.InterfaceAudience;
import org.apache.hadoop.hbase.classification.InterfaceStability;
import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
@@ -294,7 +293,7 @@ public class ParseFilter {
* @return an ArrayList containing the arguments of the filter in the filter string
*/
public static ArrayList<byte []> getFilterArguments (byte [] filterStringAsByteArray) {
- int argumentListStartIndex = KeyValue.getDelimiter(filterStringAsByteArray, 0,
+ int argumentListStartIndex = Bytes.searchDelimiterIndex(filterStringAsByteArray, 0,
filterStringAsByteArray.length,
ParseConstants.LPAREN);
if (argumentListStartIndex == -1) {
@@ -818,7 +817,8 @@ public class ParseFilter {
* @return the parsed arguments of the comparator as a 2D byte array
*/
public static byte [][] parseComparator (byte [] comparator) {
- final int index = KeyValue.getDelimiter(comparator, 0, comparator.length, ParseConstants.COLON);
+ final int index = Bytes.searchDelimiterIndex(comparator, 0, comparator.length,
+ ParseConstants.COLON);
if (index == -1) {
throw new IllegalArgumentException("Incorrect comparator");
}
http://git-wip-us.apache.org/repos/asf/hbase/blob/977f8674/hbase-client/src/test/java/org/apache/hadoop/hbase/client/TestClientNoCluster.java
----------------------------------------------------------------------
diff --git a/hbase-client/src/test/java/org/apache/hadoop/hbase/client/TestClientNoCluster.java b/hbase-client/src/test/java/org/apache/hadoop/hbase/client/TestClientNoCluster.java
index f085ace..29b32b3 100644
--- a/hbase-client/src/test/java/org/apache/hadoop/hbase/client/TestClientNoCluster.java
+++ b/hbase-client/src/test/java/org/apache/hadoop/hbase/client/TestClientNoCluster.java
@@ -32,12 +32,14 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
+import org.apache.hadoop.hbase.CellComparator;
import org.apache.commons.lang.NotImplementedException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
+import org.apache.hadoop.hbase.CellComparator;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.HConstants;
import org.apache.hadoop.hbase.HRegionInfo;
@@ -642,7 +644,7 @@ public class TestClientNoCluster extends Configured implements Tool {
* Comparator for meta row keys.
*/
private static class MetaRowsComparator implements Comparator<byte []> {
- private final KeyValue.KVComparator delegate = new KeyValue.MetaComparator();
+ private final CellComparator delegate = CellComparator.META_COMPARATOR;
@Override
public int compare(byte[] left, byte[] right) {
return delegate.compareRows(left, 0, left.length, right, 0, right.length);
http://git-wip-us.apache.org/repos/asf/hbase/blob/977f8674/hbase-client/src/test/java/org/apache/hadoop/hbase/client/TestOperation.java
----------------------------------------------------------------------
diff --git a/hbase-client/src/test/java/org/apache/hadoop/hbase/client/TestOperation.java b/hbase-client/src/test/java/org/apache/hadoop/hbase/client/TestOperation.java
index 96c4190d..37890f9 100644
--- a/hbase-client/src/test/java/org/apache/hadoop/hbase/client/TestOperation.java
+++ b/hbase-client/src/test/java/org/apache/hadoop/hbase/client/TestOperation.java
@@ -29,6 +29,7 @@ import java.util.List;
import java.util.Map;
import org.apache.hadoop.hbase.Cell;
+import org.apache.hadoop.hbase.CellComparator;
import org.apache.hadoop.hbase.CellUtil;
import org.apache.hadoop.hbase.HConstants;
import org.apache.hadoop.hbase.KeyValue;
@@ -387,7 +388,7 @@ public class TestOperation {
Assert.assertEquals(1984L, c.get(0).getTimestamp());
Assert.assertArrayEquals(VALUE, CellUtil.cloneValue(c.get(0)));
Assert.assertEquals(HConstants.LATEST_TIMESTAMP, p.getTimeStamp());
- Assert.assertEquals(0, KeyValue.COMPARATOR.compare(c.get(0), new KeyValue(c.get(0))));
+ Assert.assertEquals(0, CellComparator.COMPARATOR.compare(c.get(0), new KeyValue(c.get(0))));
p = new Put(ROW);
p.add(FAMILY, ByteBuffer.wrap(QUALIFIER), 2013L, null);
@@ -396,7 +397,7 @@ public class TestOperation {
Assert.assertEquals(2013L, c.get(0).getTimestamp());
Assert.assertArrayEquals(new byte[]{}, CellUtil.cloneValue(c.get(0)));
Assert.assertEquals(HConstants.LATEST_TIMESTAMP, p.getTimeStamp());
- Assert.assertEquals(0, KeyValue.COMPARATOR.compare(c.get(0), new KeyValue(c.get(0))));
+ Assert.assertEquals(0, CellComparator.COMPARATOR.compare(c.get(0), new KeyValue(c.get(0))));
p = new Put(ByteBuffer.wrap(ROW));
p.add(FAMILY, ByteBuffer.wrap(QUALIFIER), 2001L, null);
@@ -406,7 +407,7 @@ public class TestOperation {
Assert.assertArrayEquals(new byte[]{}, CellUtil.cloneValue(c.get(0)));
Assert.assertArrayEquals(ROW, CellUtil.cloneRow(c.get(0)));
Assert.assertEquals(HConstants.LATEST_TIMESTAMP, p.getTimeStamp());
- Assert.assertEquals(0, KeyValue.COMPARATOR.compare(c.get(0), new KeyValue(c.get(0))));
+ Assert.assertEquals(0, CellComparator.COMPARATOR.compare(c.get(0), new KeyValue(c.get(0))));
p = new Put(ByteBuffer.wrap(ROW), 1970L);
p.add(FAMILY, ByteBuffer.wrap(QUALIFIER), 2001L, null);
@@ -416,7 +417,7 @@ public class TestOperation {
Assert.assertArrayEquals(new byte[]{}, CellUtil.cloneValue(c.get(0)));
Assert.assertArrayEquals(ROW, CellUtil.cloneRow(c.get(0)));
Assert.assertEquals(1970L, p.getTimeStamp());
- Assert.assertEquals(0, KeyValue.COMPARATOR.compare(c.get(0), new KeyValue(c.get(0))));
+ Assert.assertEquals(0, CellComparator.COMPARATOR.compare(c.get(0), new KeyValue(c.get(0))));
}
@Test
http://git-wip-us.apache.org/repos/asf/hbase/blob/977f8674/hbase-common/src/main/java/org/apache/hadoop/hbase/CellComparator.java
----------------------------------------------------------------------
diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/CellComparator.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/CellComparator.java
index 540c967..904d40d 100644
--- a/hbase-common/src/main/java/org/apache/hadoop/hbase/CellComparator.java
+++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/CellComparator.java
@@ -21,6 +21,8 @@ package org.apache.hadoop.hbase;
import java.io.Serializable;
import java.util.Comparator;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.hbase.KeyValue.Type;
import org.apache.hadoop.hbase.classification.InterfaceAudience;
import org.apache.hadoop.hbase.classification.InterfaceStability;
@@ -34,6 +36,9 @@ import com.google.common.primitives.Longs;
* takes account of the special formatting of the row where we have commas to delimit table from
* regionname, from row. See KeyValue for how it has a special comparator to do hbase:meta cells
* and yet another for -ROOT-.
+ * While using this comparator for {{@link #compareRows(Cell, Cell)} et al, the hbase:meta cells format
+ * should be taken into consideration, for which the instance of this comparator
+ * should be used. In all other cases the static APIs in this comparator would be enough
*/
@edu.umd.cs.findbugs.annotations.SuppressWarnings(
value="UNKNOWN",
@@ -41,24 +46,74 @@ import com.google.common.primitives.Longs;
@InterfaceAudience.Private
@InterfaceStability.Evolving
public class CellComparator implements Comparator<Cell>, Serializable {
+ static final Log LOG = LogFactory.getLog(CellComparator.class);
private static final long serialVersionUID = -8760041766259623329L;
+ /**
+ * Comparator for plain key/values; i.e. non-catalog table key/values. Works on Key portion
+ * of KeyValue only.
+ */
+ public static final CellComparator COMPARATOR = new CellComparator();
+ /**
+ * A {@link CellComparator} for <code>hbase:meta</code> catalog table
+ * {@link KeyValue}s.
+ */
+ public static final CellComparator META_COMPARATOR = new MetaCellComparator();
+
@Override
public int compare(Cell a, Cell b) {
return compare(a, b, false);
}
/**
+ * Compares only the key portion of a cell. It does not include the sequence id/mvcc of the
+ * cell
+ * @param left
+ * @param right
+ * @return an int greater than 0 if left > than right
+ * lesser than 0 if left < than right
+ * equal to 0 if left is equal to right
+ */
+ public final int compareKeyIgnoresMvcc(Cell left, Cell right) {
+ return compare(left, right, true);
+ }
+
+ /**
+ * Used when a cell needs to be compared with a key byte[] such as cases of
+ * finding the index from the index block, bloom keys from the bloom blocks
+ * This byte[] is expected to be serialized in the KeyValue serialization format
+ * If the KeyValue (Cell's) serialization format changes this method cannot be used.
+ * @param left the cell to be compared
+ * @param key the serialized key part of a KeyValue
+ * @param offset the offset in the key byte[]
+ * @param length the length of the key byte[]
+ * @return an int greater than 0 if left is greater than right
+ * lesser than 0 if left is lesser than right
+ * equal to 0 if left is equal to right
+ * TODO : We will be moving over to
+ * compare(Cell, Cell) so that the key is also converted to a cell
+ */
+ public final int compare(Cell left, byte[] key, int offset, int length) {
+ // row
+ short rrowlength = Bytes.toShort(key, offset);
+ int c = compareRows(left, key, offset + Bytes.SIZEOF_SHORT, rrowlength);
+ if (c != 0) return c;
+
+ // Compare the rest of the two KVs without making any assumptions about
+ // the common prefix. This function will not compare rows anyway, so we
+ // don't need to tell it that the common prefix includes the row.
+ return compareWithoutRow(left, key, offset, length, rrowlength);
+ }
+
+ /**
* Compare cells.
- * TODO: Replace with dynamic rather than static comparator so can change comparator
- * implementation.
* @param a
* @param b
* @param ignoreSequenceid True if we are to compare the key portion only and ignore
* the sequenceid. Set to false to compare key and consider sequenceid.
* @return 0 if equal, -1 if a < b, and +1 if a > b.
*/
- public static int compare(final Cell a, final Cell b, boolean ignoreSequenceid) {
+ private final int compare(final Cell a, final Cell b, boolean ignoreSequenceid) {
// row
int c = compareRows(a, b);
if (c != 0) return c;
@@ -75,292 +130,481 @@ public class CellComparator implements Comparator<Cell>, Serializable {
}
}
- public static int findCommonPrefixInRowPart(Cell left, Cell right, int rowCommonPrefix) {
- return findCommonPrefix(left.getRowArray(), right.getRowArray(), left.getRowLength()
- - rowCommonPrefix, right.getRowLength() - rowCommonPrefix, left.getRowOffset()
- + rowCommonPrefix, right.getRowOffset() + rowCommonPrefix);
+ /**
+ * Compares the family and qualifier part of the cell
+ * TODO : Handle BB cases here
+ * @param left the left cell
+ * @param right the right cell
+ * @return 0 if both cells are equal, 1 if left cell is bigger than right, -1 otherwise
+ */
+ public final static int compareColumns(final Cell left, final Cell right) {
+ int lfoffset = left.getFamilyOffset();
+ int rfoffset = right.getFamilyOffset();
+ int lclength = left.getQualifierLength();
+ int rclength = right.getQualifierLength();
+ int lfamilylength = left.getFamilyLength();
+ int rfamilylength = right.getFamilyLength();
+ int diff = compareFamilies(left.getFamilyArray(), lfoffset, lfamilylength,
+ right.getFamilyArray(), rfoffset, rfamilylength);
+ if (diff != 0) {
+ return diff;
+ } else {
+ return compareQualifiers(left.getQualifierArray(), left.getQualifierOffset(), lclength,
+ right.getQualifierArray(), right.getQualifierOffset(), rclength);
+ }
}
- private static int findCommonPrefix(byte[] left, byte[] right, int leftLength, int rightLength,
- int leftOffset, int rightOffset) {
- int length = Math.min(leftLength, rightLength);
- int result = 0;
-
- while (result < length && left[leftOffset + result] == right[rightOffset + result]) {
- result++;
+ /**
+ * Compares the family and qualifier part of the cell
+ * We explicitly pass the offset and length details of the cells to avoid
+ * re-parsing of the offset and length from the cell. Used only internally.
+ * @param left
+ * @param lfamilyOffset
+ * @param lfamilylength
+ * @param lqualOffset
+ * @param lQualLength
+ * @param right
+ * @param rfamilyOffset
+ * @param rfamilylength
+ * @param rqualOffset
+ * @param rqualLength
+ * @return 0 if both cells are equal, 1 if left cell is bigger than right, -1 otherwise
+ */
+ private final static int compareColumns(final Cell left, int lfamilyOffset, int lfamilylength,
+ int lqualOffset, int lQualLength, final Cell right, final int rfamilyOffset,
+ final int rfamilylength, final int rqualOffset, int rqualLength) {
+ int diff = compareFamilies(left.getFamilyArray(), lfamilyOffset, lfamilylength,
+ right.getFamilyArray(), rfamilyOffset, rfamilylength);
+ if (diff != 0) {
+ return diff;
+ } else {
+ return compareQualifiers(left.getQualifierArray(), lqualOffset, lQualLength,
+ right.getQualifierArray(), rqualOffset, rqualLength);
}
- return result;
}
-
- public static int findCommonPrefixInFamilyPart(Cell left, Cell right, int familyCommonPrefix) {
- return findCommonPrefix(left.getFamilyArray(), right.getFamilyArray(), left.getFamilyLength()
- - familyCommonPrefix, right.getFamilyLength() - familyCommonPrefix, left.getFamilyOffset()
- + familyCommonPrefix, right.getFamilyOffset() + familyCommonPrefix);
+
+ /**
+ * Compares the family and qualifier part of a cell with a serialized Key value byte[]
+ * We explicitly pass the offset and length details of the cells to avoid
+ * re-parsing of the offset and length from the cell. Used only internally.
+ * @param left the cell to be compared
+ * @param lfamilyOffset
+ * @param lfamilylength
+ * @param lqualOffset
+ * @param lQualLength
+ * @param right the serialized key value byte array to be compared
+ * @param rfamilyOffset
+ * @param rfamilylength
+ * @param rqualOffset
+ * @param rqualLength
+ * @return 0 if both cells are equal, 1 if left cell is bigger than right, -1 otherwise
+ */
+ private final static int compareColumns(final Cell left, final int lfamilyOffset,
+ final int lfamilylength, final int lqualOffset, final int lQualLength, final byte[] right,
+ final int rfamilyOffset, final int rfamilylength, final int rqualOffset,
+ final int rqualLength) {
+ int diff = compareFamilies(left.getFamilyArray(), lfamilyOffset, lfamilylength, right,
+ rfamilyOffset, rfamilylength);
+ if (diff != 0) {
+ return diff;
+ } else {
+ return compareQualifiers(left.getQualifierArray(), lqualOffset, lQualLength, right,
+ rqualOffset, rqualLength);
+ }
}
- public static int findCommonPrefixInQualifierPart(Cell left, Cell right,
- int qualifierCommonPrefix) {
- return findCommonPrefix(left.getQualifierArray(), right.getQualifierArray(),
- left.getQualifierLength() - qualifierCommonPrefix, right.getQualifierLength()
- - qualifierCommonPrefix, left.getQualifierOffset() + qualifierCommonPrefix,
- right.getQualifierOffset() + qualifierCommonPrefix);
+ /**
+ * Compare the families of left and right cell
+ * TODO : Handle BB cases here
+ * @param left
+ * @param right
+ * @return 0 if both cells are equal, 1 if left cell is bigger than right, -1 otherwise
+ */
+ public final static int compareFamilies(Cell left, Cell right) {
+ return compareFamilies(left.getFamilyArray(), left.getFamilyOffset(), left.getFamilyLength(),
+ right.getFamilyArray(), right.getFamilyOffset(), right.getFamilyLength());
}
- /**************** equals ****************************/
+ /**
+ * We explicitly pass the offset and length details of the cells to avoid
+ * re-parsing of the offset and length from the cell. Used only internally.
+ * @param left
+ * @param lOffset
+ * @param lLength
+ * @param right
+ * @param rOffset
+ * @param rLength
+ * @return 0 if both cells are equal, 1 if left cell is bigger than right, -1 otherwise
+ */
+ private final static int compareFamilies(Cell left, int lOffset, int lLength, Cell right,
+ int rOffset, int rLength) {
+ return compareFamilies(left.getFamilyArray(), lOffset, lLength, right.getFamilyArray(),
+ rOffset, rLength);
+ }
- public static boolean equals(Cell a, Cell b){
- return equalsRow(a, b)
- && equalsFamily(a, b)
- && equalsQualifier(a, b)
- && equalsTimestamp(a, b)
- && equalsType(a, b);
+ private final static int compareFamilies(Cell left, int lOffset, int lLength, byte[] right,
+ int rOffset, int rLength) {
+ return compareFamilies(left.getFamilyArray(), lOffset, lLength, right, rOffset, rLength);
}
- public static boolean equalsRow(Cell a, Cell b){
- return Bytes.equals(
- a.getRowArray(), a.getRowOffset(), a.getRowLength(),
- b.getRowArray(), b.getRowOffset(), b.getRowLength());
+ private final static int compareFamilies(byte[] leftFamily, int lFamOffset, int lFamLength,
+ byte[] rightFamily, int rFamOffset, int rFamLen) {
+ return Bytes.compareTo(leftFamily, lFamOffset, lFamLength, rightFamily, rFamOffset, rFamLen);
}
- public static boolean equalsFamily(Cell a, Cell b){
- return Bytes.equals(
- a.getFamilyArray(), a.getFamilyOffset(), a.getFamilyLength(),
- b.getFamilyArray(), b.getFamilyOffset(), b.getFamilyLength());
+ /**
+ * Compare the qualifiers part of the left and right cells.
+ * TODO : Handle BB cases here
+ * @param left
+ * @param right
+ * @return 0 if both cells are equal, 1 if left cell is bigger than right, -1 otherwise
+ */
+ public final static int compareQualifiers(Cell left, Cell right) {
+ return compareQualifiers(left.getQualifierArray(), left.getQualifierOffset(),
+ left.getQualifierLength(), right.getQualifierArray(), right.getQualifierOffset(),
+ right.getQualifierLength());
}
- public static boolean equalsQualifier(Cell a, Cell b){
- return Bytes.equals(
- a.getQualifierArray(), a.getQualifierOffset(), a.getQualifierLength(),
- b.getQualifierArray(), b.getQualifierOffset(), b.getQualifierLength());
+ /**
+ * We explicitly pass the offset and length details of the cells to avoid
+ * re-parsing of the offset and length from the cell. Used only internally.
+ * @param left
+ * @param lOffset
+ * @param lLength
+ * @param right
+ * @param rOffset
+ * @param rLength
+ * @return 0 if both cells are equal, 1 if left cell is bigger than right, -1 otherwise
+ */
+ private final static int compareQualifiers(Cell left, int lOffset, int lLength, Cell right,
+ int rOffset, int rLength) {
+ return compareQualifiers(left.getQualifierArray(), lOffset,
+ lLength, right.getQualifierArray(), rOffset,
+ rLength);
}
- public static boolean equalsTimestamp(Cell a, Cell b){
- return a.getTimestamp() == b.getTimestamp();
+ /**
+ * We explicitly pass the offset and length details of the cells to avoid
+ * re-parsing of the offset and length from the cell. Used only internally.
+ * @param left
+ * @param lOffset
+ * @param lLength
+ * @param right
+ * @param rOffset
+ * @param rLength
+ * @return 0 if both cells are equal, 1 if left cell is bigger than right, -1 otherwise
+ */
+ private final static int compareQualifiers(Cell left, int lOffset, int lLength, byte[] right,
+ int rOffset, int rLength) {
+ return compareQualifiers(left.getQualifierArray(), lOffset,
+ lLength, right, rOffset,
+ rLength);
}
- public static boolean equalsType(Cell a, Cell b){
- return a.getTypeByte() == b.getTypeByte();
+ private static int compareQualifiers(byte[] leftCol, int lColOffset, int lColLength,
+ byte[] rightCol, int rColOffset, int rColLength) {
+ return Bytes.compareTo(leftCol, lColOffset, lColLength, rightCol, rColOffset, rColLength);
}
- public static int compareColumns(final Cell left, final Cell right) {
- int lfoffset = left.getFamilyOffset();
- int rfoffset = right.getFamilyOffset();
- int lclength = left.getQualifierLength();
- int rclength = right.getQualifierLength();
- int lfamilylength = left.getFamilyLength();
- int rfamilylength = right.getFamilyLength();
- int diff = compare(left.getFamilyArray(), lfoffset, lfamilylength, right.getFamilyArray(),
- rfoffset, rfamilylength);
- if (diff != 0) {
- return diff;
- } else {
- return compare(left.getQualifierArray(), left.getQualifierOffset(), lclength,
- right.getQualifierArray(), right.getQualifierOffset(), rclength);
+ /**
+ * Compare columnFamily, qualifier, timestamp, and key type (everything
+ * except the row). This method is used both in the normal comparator and
+ * the "same-prefix" comparator. Note that we are assuming that row portions
+ * of both KVs have already been parsed and found identical, and we don't
+ * validate that assumption here.
+ * TODO : we will have to handle BB cases here
+ * @param commonPrefix
+ * the length of the common prefix of the two key-values being
+ * compared, including row length and row
+ */
+ private final int compareWithoutRow(Cell left,
+ byte[] right, int roffset, int rlength, short rowlength) {
+ /***
+ * KeyValue Format and commonLength:
+ * |_keyLen_|_valLen_|_rowLen_|_rowKey_|_famiLen_|_fami_|_Quali_|....
+ * ------------------|-------commonLength--------|--------------
+ */
+ int commonLength = KeyValue.ROW_LENGTH_SIZE + KeyValue.FAMILY_LENGTH_SIZE + rowlength;
+
+ // commonLength + TIMESTAMP_TYPE_SIZE
+ int commonLengthWithTSAndType = KeyValue.TIMESTAMP_TYPE_SIZE + commonLength;
+ // ColumnFamily + Qualifier length.
+ int lcolumnlength = left.getFamilyLength() + left.getQualifierLength();
+ int rcolumnlength = rlength - commonLengthWithTSAndType;
+
+ byte ltype = left.getTypeByte();
+ byte rtype = right[roffset + (rlength - 1)];
+
+ // If the column is not specified, the "minimum" key type appears the
+ // latest in the sorted order, regardless of the timestamp. This is used
+ // for specifying the last key/value in a given row, because there is no
+ // "lexicographically last column" (it would be infinitely long). The
+ // "maximum" key type does not need this behavior.
+ if (lcolumnlength == 0 && ltype == Type.Minimum.getCode()) {
+ // left is "bigger", i.e. it appears later in the sorted order
+ return 1;
+ }
+ if (rcolumnlength == 0 && rtype == Type.Minimum.getCode()) {
+ return -1;
}
- }
- public static int compareFamilies(Cell left, Cell right) {
- return Bytes.compareTo(left.getFamilyArray(), left.getFamilyOffset(), left.getFamilyLength(),
- right.getFamilyArray(), right.getFamilyOffset(), right.getFamilyLength());
- }
+ int lfamilyoffset = left.getFamilyOffset();
+ int rfamilyoffset = commonLength + roffset;
- public static int compareQualifiers(Cell left, Cell right) {
- return Bytes.compareTo(left.getQualifierArray(), left.getQualifierOffset(),
- left.getQualifierLength(), right.getQualifierArray(), right.getQualifierOffset(),
- right.getQualifierLength());
- }
+ // Column family length.
+ int lfamilylength = left.getFamilyLength();
+ int rfamilylength = right[rfamilyoffset - 1];
+ // If left family size is not equal to right family size, we need not
+ // compare the qualifiers.
+ boolean sameFamilySize = (lfamilylength == rfamilylength);
+ if (!sameFamilySize) {
+ // comparing column family is enough.
+ return compareFamilies(left, lfamilyoffset, lfamilylength, right,
+ rfamilyoffset, rfamilylength);
+ }
+ // Compare family & qualifier together.
+ // Families are same. Compare on qualifiers.
+ int lQualOffset = left.getQualifierOffset();
+ int lQualLength = left.getQualifierLength();
+ int comparison = compareColumns(left, lfamilyoffset, lfamilylength, lQualOffset, lQualLength,
+ right, rfamilyoffset, rfamilylength, rfamilyoffset + rfamilylength,
+ (rcolumnlength - rfamilylength));
+ if (comparison != 0) {
+ return comparison;
+ }
- public int compareFlatKey(Cell left, Cell right) {
- int compare = compareRows(left, right);
+ // //
+ // Next compare timestamps.
+ long rtimestamp = Bytes.toLong(right, roffset + (rlength - KeyValue.TIMESTAMP_TYPE_SIZE));
+ int compare = compareTimestamps(left.getTimestamp(), rtimestamp);
if (compare != 0) {
return compare;
}
- return compareWithoutRow(left, right);
+
+ // Compare types. Let the delete types sort ahead of puts; i.e. types
+ // of higher numbers sort before those of lesser numbers. Maximum (255)
+ // appears ahead of everything, and minimum (0) appears after
+ // everything.
+ return (0xff & rtype) - (0xff & ltype);
}
/**
- * Do not use comparing rows from hbase:meta. Meta table Cells have schema (table,startrow,hash)
- * so can't be treated as plain byte arrays as this method does.
+ * Compares the rows of the left and right cell
+ * For the hbase:meta case the
+ * ({@link #compareRows(byte[], int, int, byte[], int, int)} is overridden such
+ * that it can handle the hbase:meta cells. The caller should ensure using the
+ * appropriate comparator for hbase:meta
+ * TODO : Handle BB cases here
+ * @param left
+ * @param right
+ * @return 0 if both cells are equal, 1 if left cell is bigger than right, -1 otherwise
*/
- public static int compareRows(final Cell left, final Cell right) {
- return Bytes.compareTo(left.getRowArray(), left.getRowOffset(), left.getRowLength(),
+ public final int compareRows(final Cell left, final Cell right) {
+ return compareRows(left.getRowArray(), left.getRowOffset(), left.getRowLength(),
right.getRowArray(), right.getRowOffset(), right.getRowLength());
}
/**
+ * Compares the rows of two cells
+ * We explicitly pass the offset and length details of the cell to avoid re-parsing
+ * of the offset and length from the cell
+ * @param left the cell to be compared
+ * @param loffset the row offset of the left cell
+ * @param llength the row length of the left cell
+ * @param right the cell to be compared
+ * @param roffset the row offset of the right cell
+ * @param rlength the row length of the right cell
+ * @return 0 if both cells are equal, 1 if left cell is bigger than right, -1 otherwise
+ */
+ private final int compareRows(Cell left, int loffset, int llength, Cell right, int roffset,
+ int rlength) {
+ // TODO : for BB based cells all the hasArray based checks would happen
+ // here. But we may have
+ // to end up in multiple APIs accepting byte[] and BBs
+ return compareRows(left.getRowArray(), loffset, llength, right.getRowArray(), roffset,
+ rlength);
+ }
+
+ /**
+ * Compares the row part of the cell with a simple plain byte[] like the
+ * stopRow in Scan. This should be used with context where for hbase:meta
+ * cells the {{@link #META_COMPARATOR} should be used
+ *
+ * @param left
+ * the cell to be compared
+ * @param right
+ * the kv serialized byte[] to be compared with
+ * @param roffset
+ * the offset in the byte[]
+ * @param rlength
+ * the length in the byte[]
+ * @return 0 if both cell and the byte[] are equal, 1 if the cell is bigger
+ * than byte[], -1 otherwise
+ */
+ public final int compareRows(Cell left, byte[] right, int roffset,
+ int rlength) {
+ // TODO : for BB based cells all the hasArray based checks would happen
+ // here. But we may have
+ // to end up in multiple APIs accepting byte[] and BBs
+ return compareRows(left.getRowArray(), left.getRowOffset(), left.getRowLength(), right,
+ roffset, rlength);
+ }
+ /**
* Do not use comparing rows from hbase:meta. Meta table Cells have schema (table,startrow,hash)
* so can't be treated as plain byte arrays as this method does.
*/
- public static int compareRows(byte[] left, int loffset, int llength, byte[] right, int roffset,
+ // TODO : CLEANUP : in order to do this we may have to modify some code
+ // HRegion.next() and will involve a
+ // Filter API change also. Better to do that later along with
+ // HBASE-11425/HBASE-13387.
+ public int compareRows(byte[] left, int loffset, int llength, byte[] right, int roffset,
int rlength) {
return Bytes.compareTo(left, loffset, llength, right, roffset, rlength);
}
- public static int compareWithoutRow(final Cell leftCell, final Cell rightCell) {
+ private static int compareWithoutRow(final Cell left, final Cell right) {
// If the column is not specified, the "minimum" key type appears the
// latest in the sorted order, regardless of the timestamp. This is used
// for specifying the last key/value in a given row, because there is no
// "lexicographically last column" (it would be infinitely long). The
// "maximum" key type does not need this behavior.
// Copied from KeyValue. This is bad in that we can't do memcmp w/ special rules like this.
- // TODO
- if (leftCell.getFamilyLength() + leftCell.getQualifierLength() == 0
- && leftCell.getTypeByte() == Type.Minimum.getCode()) {
+ int lFamLength = left.getFamilyLength();
+ int rFamLength = right.getFamilyLength();
+ int lQualLength = left.getQualifierLength();
+ int rQualLength = right.getQualifierLength();
+ if (lFamLength + lQualLength == 0
+ && left.getTypeByte() == Type.Minimum.getCode()) {
// left is "bigger", i.e. it appears later in the sorted order
return 1;
}
- if (rightCell.getFamilyLength() + rightCell.getQualifierLength() == 0
- && rightCell.getTypeByte() == Type.Minimum.getCode()) {
+ if (rFamLength + rQualLength == 0
+ && right.getTypeByte() == Type.Minimum.getCode()) {
return -1;
}
- boolean sameFamilySize = (leftCell.getFamilyLength() == rightCell.getFamilyLength());
+ boolean sameFamilySize = (lFamLength == rFamLength);
+ int lFamOffset = left.getFamilyOffset();
+ int rFamOffset = right.getFamilyOffset();
if (!sameFamilySize) {
// comparing column family is enough.
-
- return Bytes.compareTo(leftCell.getFamilyArray(), leftCell.getFamilyOffset(),
- leftCell.getFamilyLength(), rightCell.getFamilyArray(), rightCell.getFamilyOffset(),
- rightCell.getFamilyLength());
+ return compareFamilies(left, lFamOffset, lFamLength, right, rFamOffset, rFamLength);
}
- int diff = compareColumns(leftCell, rightCell);
+ // Families are same. Compare on qualifiers.
+ int lQualOffset = left.getQualifierOffset();
+ int rQualOffset = right.getQualifierOffset();
+ int diff = compareColumns(left, lFamOffset, lFamLength, lQualOffset, lQualLength, right,
+ rFamOffset, rFamLength, rQualOffset, rQualLength);
if (diff != 0) return diff;
- diff = compareTimestamps(leftCell, rightCell);
+ diff = compareTimestamps(left, right);
if (diff != 0) return diff;
// Compare types. Let the delete types sort ahead of puts; i.e. types
// of higher numbers sort before those of lesser numbers. Maximum (255)
// appears ahead of everything, and minimum (0) appears after
// everything.
- return (0xff & rightCell.getTypeByte()) - (0xff & leftCell.getTypeByte());
+ return (0xff & right.getTypeByte()) - (0xff & left.getTypeByte());
}
- public static int compareTimestamps(final Cell left, final Cell right) {
- long ltimestamp = left.getTimestamp();
- long rtimestamp = right.getTimestamp();
- return compareTimestamps(ltimestamp, rtimestamp);
- }
-
- /********************* hashCode ************************/
-
/**
- * Returns a hash code that is always the same for two Cells having a matching equals(..) result.
+ * Compare the timestamp of the left and right cell
+ *
+ * @param left
+ * @param right
+ * @return 0 if equal, -1 if left's ts is less than right's ts, 1 if left's ts
+ * is greater than right's ts
*/
- public static int hashCode(Cell cell){
- if (cell == null) {// return 0 for empty Cell
- return 0;
- }
-
- int hash = calculateHashForKeyValue(cell);
- hash = 31 * hash + (int)cell.getMvccVersion();
- return hash;
+ public static int compareTimestamps(final Cell left, final Cell right) {
+ return compareTimestamps(left.getTimestamp(), right.getTimestamp());
}
/**
- * Returns a hash code that is always the same for two Cells having a matching
- * equals(..) result. Note : Ignore mvcc while calculating the hashcode
- *
- * @param cell
- * @return hashCode
+ * Used to compare two cells based on the column hint provided. This is specifically
+ * used when we need to optimize the seeks based on the next indexed key. This is an
+ * advance usage API specifically needed for some optimizations.
+ * @param nextIndexedCell the next indexed cell
+ * @param currentCell the cell to be compared
+ * @param foff the family offset of the currentCell
+ * @param flen the family length of the currentCell
+ * @param colHint the column hint provided - could be null
+ * @param coff the offset of the column hint if provided, if not offset of the currentCell's
+ * qualifier
+ * @param clen the length of the column hint if provided, if not length of the currentCell's
+ * qualifier
+ * @param ts the timestamp to be seeked
+ * @param type the type to be seeked
+ * @return an int based on the given column hint
+ * TODO : To be moved out of here because this is a special API used in scan
+ * optimization.
*/
- public static int hashCodeIgnoreMvcc(Cell cell) {
- if (cell == null) {// return 0 for empty Cell
- return 0;
+ // compare a key against row/fam/qual/ts/type
+ public final int compareKeyBasedOnColHint(Cell nextIndexedCell, Cell currentCell, int foff,
+ int flen, byte[] colHint, int coff, int clen, long ts, byte type) {
+
+ int compare = 0;
+ compare = compareRows(nextIndexedCell, nextIndexedCell.getRowOffset(),
+ nextIndexedCell.getRowLength(), currentCell, currentCell.getRowOffset(),
+ currentCell.getRowLength());
+ if (compare != 0) {
+ return compare;
+ }
+ // If the column is not specified, the "minimum" key type appears the
+ // latest in the sorted order, regardless of the timestamp. This is used
+ // for specifying the last key/value in a given row, because there is no
+ // "lexicographically last column" (it would be infinitely long). The
+ // "maximum" key type does not need this behavior.
+ if (nextIndexedCell.getFamilyLength() + nextIndexedCell.getQualifierLength() == 0
+ && nextIndexedCell.getTypeByte() == Type.Minimum.getCode()) {
+ // left is "bigger", i.e. it appears later in the sorted order
+ return 1;
+ }
+ int qualLen = currentCell.getQualifierLength();
+ if (flen + clen == 0 && type == Type.Minimum.getCode()) {
+ return -1;
}
- int hash = calculateHashForKeyValue(cell);
- return hash;
- }
-
- private static int calculateHashForKeyValue(Cell cell) {
- //pre-calculate the 3 hashes made of byte ranges
- int rowHash = Bytes.hashCode(cell.getRowArray(), cell.getRowOffset(), cell.getRowLength());
- int familyHash =
- Bytes.hashCode(cell.getFamilyArray(), cell.getFamilyOffset(), cell.getFamilyLength());
- int qualifierHash = Bytes.hashCode(cell.getQualifierArray(), cell.getQualifierOffset(),
- cell.getQualifierLength());
-
- //combine the 6 sub-hashes
- int hash = 31 * rowHash + familyHash;
- hash = 31 * hash + qualifierHash;
- hash = 31 * hash + (int)cell.getTimestamp();
- hash = 31 * hash + cell.getTypeByte();
- return hash;
- }
-
-
- /******************** lengths *************************/
-
- public static boolean areKeyLengthsEqual(Cell a, Cell b) {
- return a.getRowLength() == b.getRowLength()
- && a.getFamilyLength() == b.getFamilyLength()
- && a.getQualifierLength() == b.getQualifierLength();
- }
-
- public static boolean areRowLengthsEqual(Cell a, Cell b) {
- return a.getRowLength() == b.getRowLength();
- }
-
-
- /*********************common prefixes*************************/
-
- private static int compare(byte[] left, int leftOffset, int leftLength, byte[] right,
- int rightOffset, int rightLength) {
- return Bytes.compareTo(left, leftOffset, leftLength, right, rightOffset, rightLength);
- }
-
- public static int compareCommonRowPrefix(Cell left, Cell right, int rowCommonPrefix) {
- return compare(left.getRowArray(), left.getRowOffset() + rowCommonPrefix, left.getRowLength()
- - rowCommonPrefix, right.getRowArray(), right.getRowOffset() + rowCommonPrefix,
- right.getRowLength() - rowCommonPrefix);
- }
-
- public static int compareCommonFamilyPrefix(Cell left, Cell right,
- int familyCommonPrefix) {
- return compare(left.getFamilyArray(), left.getFamilyOffset() + familyCommonPrefix,
- left.getFamilyLength() - familyCommonPrefix, right.getFamilyArray(),
- right.getFamilyOffset() + familyCommonPrefix,
- right.getFamilyLength() - familyCommonPrefix);
- }
+ compare = compareFamilies(nextIndexedCell, nextIndexedCell.getFamilyOffset(),
+ nextIndexedCell.getFamilyLength(), currentCell, currentCell.getFamilyOffset(),
+ flen);
+ if (compare != 0) {
+ return compare;
+ }
+ if (colHint == null) {
+ compare = compareQualifiers(nextIndexedCell, nextIndexedCell.getQualifierOffset(),
+ nextIndexedCell.getQualifierLength(), currentCell, currentCell.getQualifierOffset(),
+ qualLen);
+ } else {
+ compare = compareQualifiers(nextIndexedCell, nextIndexedCell.getQualifierOffset(),
+ nextIndexedCell.getQualifierLength(), colHint, coff, clen);
+ }
+ if (compare != 0) {
+ return compare;
+ }
+ // Next compare timestamps.
+ compare = compareTimestamps(nextIndexedCell.getTimestamp(), ts);
+ if (compare != 0) {
+ return compare;
+ }
- public static int compareCommonQualifierPrefix(Cell left, Cell right,
- int qualCommonPrefix) {
- return compare(left.getQualifierArray(), left.getQualifierOffset() + qualCommonPrefix,
- left.getQualifierLength() - qualCommonPrefix, right.getQualifierArray(),
- right.getQualifierOffset() + qualCommonPrefix, right.getQualifierLength()
- - qualCommonPrefix);
+ // Compare types. Let the delete types sort ahead of puts; i.e. types
+ // of higher numbers sort before those of lesser numbers. Maximum (255)
+ // appears ahead of everything, and minimum (0) appears after
+ // everything.
+ return (0xff & type) - (0xff & nextIndexedCell.getTypeByte());
}
- /***************** special cases ****************************/
/**
- * special case for KeyValue.equals
+ * The below older timestamps sorting ahead of newer timestamps looks
+ * wrong but it is intentional. This way, newer timestamps are first
+ * found when we iterate over a memstore and newer versions are the
+ * first we trip over when reading from a store file.
+ * @param ltimestamp
+ * @param rtimestamp
+ * @return 1 if left timestamp > right timestamp
+ * -1 if left timestamp < right timestamp
+ * 0 if both timestamps are equal
*/
- public static boolean equalsIgnoreMvccVersion(Cell a, Cell b){
- return 0 == compareStaticIgnoreMvccVersion(a, b);
- }
-
- private static int compareStaticIgnoreMvccVersion(Cell a, Cell b) {
- // row
- int c = compareRows(a, b);
- if (c != 0) return c;
-
- // family
- c = compareColumns(a, b);
- if (c != 0) return c;
-
- // timestamp: later sorts first
- c = compareTimestamps(a, b);
- if (c != 0) return c;
-
- //type
- c = (0xff & b.getTypeByte()) - (0xff & a.getTypeByte());
- return c;
- }
-
- private static int compareTimestamps(final long ltimestamp, final long rtimestamp) {
- // The below older timestamps sorting ahead of newer timestamps looks
- // wrong but it is intentional. This way, newer timestamps are first
- // found when we iterate over a memstore and newer versions are the
- // first we trip over when reading from a store file.
+ public static int compareTimestamps(final long ltimestamp, final long rtimestamp) {
if (ltimestamp < rtimestamp) {
return 1;
} else if (ltimestamp > rtimestamp) {
@@ -370,7 +614,7 @@ public class CellComparator implements Comparator<Cell>, Serializable {
}
/**
- * Counter part for the KeyValue.RowOnlyComparator
+ * Comparator that compares row component only of a Cell
*/
public static class RowComparator extends CellComparator {
@Override
@@ -380,119 +624,61 @@ public class CellComparator implements Comparator<Cell>, Serializable {
}
/**
- * Try to return a Cell that falls between <code>left</code> and <code>right</code> but that is
- * shorter; i.e. takes up less space. This trick is used building HFile block index.
- * Its an optimization. It does not always work. In this case we'll just return the
- * <code>right</code> cell.
- * @param comparator Comparator to use.
- * @param left
- * @param right
- * @return A cell that sorts between <code>left</code> and <code>right</code>.
- */
- public static Cell getMidpoint(final KeyValue.KVComparator comparator, final Cell left,
- final Cell right) {
- // TODO: Redo so only a single pass over the arrays rather than one to compare and then a
- // second composing midpoint.
- if (right == null) {
- throw new IllegalArgumentException("right cell can not be null");
- }
- if (left == null) {
- return right;
- }
- // If Cells from meta table, don't mess around. meta table Cells have schema
- // (table,startrow,hash) so can't be treated as plain byte arrays. Just skip out without
- // trying to do this optimization.
- if (comparator != null && comparator instanceof KeyValue.MetaComparator) {
- return right;
- }
- int diff = compareRows(left, right);
- if (diff > 0) {
- throw new IllegalArgumentException("Left row sorts after right row; left=" +
- CellUtil.getCellKeyAsString(left) + ", right=" + CellUtil.getCellKeyAsString(right));
- }
- if (diff < 0) {
- // Left row is < right row.
- byte [] midRow = getMinimumMidpointArray(left.getRowArray(), left.getRowOffset(),
- left.getRowLength(),
- right.getRowArray(), right.getRowOffset(), right.getRowLength());
- // If midRow is null, just return 'right'. Can't do optimization.
- if (midRow == null) return right;
- return CellUtil.createCell(midRow);
- }
- // Rows are same. Compare on families.
- diff = compareFamilies(left, right);
- if (diff > 0) {
- throw new IllegalArgumentException("Left family sorts after right family; left=" +
- CellUtil.getCellKeyAsString(left) + ", right=" + CellUtil.getCellKeyAsString(right));
- }
- if (diff < 0) {
- byte [] midRow = getMinimumMidpointArray(left.getFamilyArray(), left.getFamilyOffset(),
- left.getFamilyLength(),
- right.getFamilyArray(), right.getFamilyOffset(), right.getFamilyLength());
- // If midRow is null, just return 'right'. Can't do optimization.
- if (midRow == null) return right;
- // Return new Cell where we use right row and then a mid sort family.
- return CellUtil.createCell(right.getRowArray(), right.getRowOffset(), right.getRowLength(),
- midRow, 0, midRow.length, HConstants.EMPTY_BYTE_ARRAY, 0,
- HConstants.EMPTY_BYTE_ARRAY.length);
- }
- // Families are same. Compare on qualifiers.
- diff = compareQualifiers(left, right);
- if (diff > 0) {
- throw new IllegalArgumentException("Left qualifier sorts after right qualifier; left=" +
- CellUtil.getCellKeyAsString(left) + ", right=" + CellUtil.getCellKeyAsString(right));
- }
- if (diff < 0) {
- byte [] midRow = getMinimumMidpointArray(left.getQualifierArray(), left.getQualifierOffset(),
- left.getQualifierLength(),
- right.getQualifierArray(), right.getQualifierOffset(), right.getQualifierLength());
- // If midRow is null, just return 'right'. Can't do optimization.
- if (midRow == null) return right;
- // Return new Cell where we use right row and family and then a mid sort qualifier.
- return CellUtil.createCell(right.getRowArray(), right.getRowOffset(), right.getRowLength(),
- right.getFamilyArray(), right.getFamilyOffset(), right.getFamilyLength(),
- midRow, 0, midRow.length);
- }
- // No opportunity for optimization. Just return right key.
- return right;
- }
-
- /**
- * @param leftArray
- * @param leftOffset
- * @param leftLength
- * @param rightArray
- * @param rightOffset
- * @param rightLength
- * @return Return a new array that is between left and right and minimally sized else just return
- * null as indicator that we could not create a mid point.
+ * A {@link CellComparator} for <code>hbase:meta</code> catalog table
+ * {@link KeyValue}s.
*/
- private static byte [] getMinimumMidpointArray(final byte [] leftArray, final int leftOffset,
- final int leftLength,
- final byte [] rightArray, final int rightOffset, final int rightLength) {
- // rows are different
- int minLength = leftLength < rightLength ? leftLength : rightLength;
- short diffIdx = 0;
- while (diffIdx < minLength &&
- leftArray[leftOffset + diffIdx] == rightArray[rightOffset + diffIdx]) {
- diffIdx++;
- }
- byte [] minimumMidpointArray = null;
- if (diffIdx >= minLength) {
- // leftKey's row is prefix of rightKey's.
- minimumMidpointArray = new byte[diffIdx + 1];
- System.arraycopy(rightArray, rightOffset, minimumMidpointArray, 0, diffIdx + 1);
- } else {
- int diffByte = leftArray[leftOffset + diffIdx];
- if ((0xff & diffByte) < 0xff && (diffByte + 1) < (rightArray[rightOffset + diffIdx] & 0xff)) {
- minimumMidpointArray = new byte[diffIdx + 1];
- System.arraycopy(leftArray, leftOffset, minimumMidpointArray, 0, diffIdx);
- minimumMidpointArray[diffIdx] = (byte) (diffByte + 1);
+ public static class MetaCellComparator extends CellComparator {
+
+ @Override
+ public int compareRows(byte[] left, int loffset, int llength, byte[] right, int roffset,
+ int rlength) {
+ int leftDelimiter = Bytes.searchDelimiterIndex(left, loffset, llength, HConstants.DELIMITER);
+ int rightDelimiter = Bytes
+ .searchDelimiterIndex(right, roffset, rlength, HConstants.DELIMITER);
+ // Compare up to the delimiter
+ int lpart = (leftDelimiter < 0 ? llength : leftDelimiter - loffset);
+ int rpart = (rightDelimiter < 0 ? rlength : rightDelimiter - roffset);
+ int result = Bytes.compareTo(left, loffset, lpart, right, roffset, rpart);
+ if (result != 0) {
+ return result;
+ } else {
+ if (leftDelimiter < 0 && rightDelimiter >= 0) {
+ return -1;
+ } else if (rightDelimiter < 0 && leftDelimiter >= 0) {
+ return 1;
+ } else if (leftDelimiter < 0 && rightDelimiter < 0) {
+ return 0;
+ }
+ }
+ // Compare middle bit of the row.
+ // Move past delimiter
+ leftDelimiter++;
+ rightDelimiter++;
+ int leftFarDelimiter = Bytes.searchDelimiterIndexInReverse(left, leftDelimiter, llength
+ - (leftDelimiter - loffset), HConstants.DELIMITER);
+ int rightFarDelimiter = Bytes.searchDelimiterIndexInReverse(right, rightDelimiter, rlength
+ - (rightDelimiter - roffset), HConstants.DELIMITER);
+ // Now compare middlesection of row.
+ lpart = (leftFarDelimiter < 0 ? llength + loffset : leftFarDelimiter) - leftDelimiter;
+ rpart = (rightFarDelimiter < 0 ? rlength + roffset : rightFarDelimiter) - rightDelimiter;
+ result = super.compareRows(left, leftDelimiter, lpart, right, rightDelimiter, rpart);
+ if (result != 0) {
+ return result;
} else {
- minimumMidpointArray = new byte[diffIdx + 1];
- System.arraycopy(rightArray, rightOffset, minimumMidpointArray, 0, diffIdx + 1);
+ if (leftDelimiter < 0 && rightDelimiter >= 0) {
+ return -1;
+ } else if (rightDelimiter < 0 && leftDelimiter >= 0) {
+ return 1;
+ } else if (leftDelimiter < 0 && rightDelimiter < 0) {
+ return 0;
+ }
}
+ // Compare last part of row, the rowid.
+ leftFarDelimiter++;
+ rightFarDelimiter++;
+ result = Bytes.compareTo(left, leftFarDelimiter, llength - (leftFarDelimiter - loffset),
+ right, rightFarDelimiter, rlength - (rightFarDelimiter - roffset));
+ return result;
}
- return minimumMidpointArray;
}
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/hbase/blob/977f8674/hbase-common/src/main/java/org/apache/hadoop/hbase/CellUtil.java
----------------------------------------------------------------------
diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/CellUtil.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/CellUtil.java
index bce3957..7ddcfe6 100644
--- a/hbase-common/src/main/java/org/apache/hadoop/hbase/CellUtil.java
+++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/CellUtil.java
@@ -26,6 +26,7 @@ import java.util.List;
import java.util.Map.Entry;
import java.util.NavigableMap;
+import org.apache.hadoop.hbase.CellComparator.MetaCellComparator;
import org.apache.hadoop.hbase.KeyValue.Type;
import org.apache.hadoop.hbase.classification.InterfaceAudience;
import org.apache.hadoop.hbase.classification.InterfaceStability;
@@ -379,8 +380,10 @@ public final class CellUtil {
}
public static boolean matchingRow(final Cell left, final byte[] buf) {
- return Bytes.equals(left.getRowArray(), left.getRowOffset(), left.getRowLength(), buf, 0,
- buf.length);
+ if (buf == null) {
+ return left.getQualifierLength() == 0;
+ }
+ return matchingRow(left, buf, 0, buf.length);
}
public static boolean matchingRow(final Cell left, final byte[] buf, final int offset,
@@ -395,8 +398,10 @@ public final class CellUtil {
}
public static boolean matchingFamily(final Cell left, final byte[] buf) {
- return Bytes.equals(left.getFamilyArray(), left.getFamilyOffset(), left.getFamilyLength(), buf,
- 0, buf.length);
+ if (buf == null) {
+ return left.getFamilyLength() == 0;
+ }
+ return matchingFamily(left, buf, 0, buf.length);
}
public static boolean matchingFamily(final Cell left, final byte[] buf, final int offset,
@@ -411,14 +416,29 @@ public final class CellUtil {
right.getQualifierLength());
}
+ /**
+ * Finds if the qualifier part of the cell and the KV serialized
+ * byte[] are equal
+ * @param left
+ * @param buf the serialized keyvalue format byte[]
+ * @return true if the qualifier matches, false otherwise
+ */
public static boolean matchingQualifier(final Cell left, final byte[] buf) {
if (buf == null) {
return left.getQualifierLength() == 0;
}
- return Bytes.equals(left.getQualifierArray(), left.getQualifierOffset(),
- left.getQualifierLength(), buf, 0, buf.length);
+ return matchingQualifier(left, buf, 0, buf.length);
}
+ /**
+ * Finds if the qualifier part of the cell and the KV serialized
+ * byte[] are equal
+ * @param left
+ * @param buf the serialized keyvalue format byte[]
+ * @param offset the offset of the qualifier in the byte[]
+ * @param length the length of the qualifier in the byte[]
+ * @return true if the qualifier matches, false otherwise
+ */
public static boolean matchingQualifier(final Cell left, final byte[] buf, final int offset,
final int length) {
if (buf == null) {
@@ -902,4 +922,118 @@ public final class CellUtil {
return builder.toString();
}
+
+ /***************** special cases ****************************/
+
+ /**
+ * special case for Cell.equals
+ */
+ public static boolean equalsIgnoreMvccVersion(Cell a, Cell b) {
+ // row
+ boolean res = matchingRow(a, b);
+ if (!res)
+ return res;
+
+ // family
+ res = matchingColumn(a, b);
+ if (!res)
+ return res;
+
+ // timestamp: later sorts first
+ if (!matchingTimestamp(a, b))
+ return false;
+
+ // type
+ int c = (0xff & b.getTypeByte()) - (0xff & a.getTypeByte());
+ if (c != 0)
+ return false;
+ else return true;
+ }
+
+ /**************** equals ****************************/
+
+ public static boolean equals(Cell a, Cell b) {
+ return matchingRow(a, b) && matchingFamily(a, b) && matchingQualifier(a, b)
+ && matchingTimestamp(a, b) && matchingType(a, b);
+ }
+
+ public static boolean matchingTimestamp(Cell a, Cell b) {
+ return CellComparator.compareTimestamps(a.getTimestamp(), b.getTimestamp()) == 0;
+ }
+
+ public static boolean matchingType(Cell a, Cell b) {
+ return a.getTypeByte() == b.getTypeByte();
+ }
+
+ /**
+ * Compares the row of two keyvalues for equality
+ *
+ * @param left
+ * @param right
+ * @return True if rows match.
+ */
+ public static boolean matchingRows(final Cell left, final Cell right) {
+ short lrowlength = left.getRowLength();
+ short rrowlength = right.getRowLength();
+ return matchingRows(left, lrowlength, right, rrowlength);
+ }
+
+ /**
+ * @param left
+ * @param lrowlength
+ * @param right
+ * @param rrowlength
+ * @return True if rows match.
+ */
+ private static boolean matchingRows(final Cell left, final short lrowlength, final Cell right,
+ final short rrowlength) {
+ return lrowlength == rrowlength
+ && matchingRows(left.getRowArray(), left.getRowOffset(), lrowlength, right.getRowArray(),
+ right.getRowOffset(), rrowlength);
+ }
+
+ /**
+ * Compare rows. Just calls Bytes.equals, but it's good to have this
+ * encapsulated.
+ *
+ * @param left
+ * Left row array.
+ * @param loffset
+ * Left row offset.
+ * @param llength
+ * Left row length.
+ * @param right
+ * Right row array.
+ * @param roffset
+ * Right row offset.
+ * @param rlength
+ * Right row length.
+ * @return Whether rows are the same row.
+ */
+ private static boolean matchingRows(final byte[] left, final int loffset, final int llength,
+ final byte[] right, final int roffset, final int rlength) {
+ return Bytes.equals(left, loffset, llength, right, roffset, rlength);
+ }
+
+ /**
+ * Compares the row and column of two keyvalues for equality
+ *
+ * @param left
+ * @param right
+ * @return True if same row and column.
+ */
+ public static boolean matchingRowColumn(final Cell left, final Cell right) {
+ short lrowlength = left.getRowLength();
+ short rrowlength = right.getRowLength();
+
+ if ((lrowlength + left.getFamilyLength() + left.getQualifierLength()) != (rrowlength
+ + right.getFamilyLength() + right.getQualifierLength())) {
+ return false;
+ }
+
+ if (!matchingRows(left, lrowlength, right, rrowlength)) {
+ return false;
+ }
+ return matchingColumn(left, right);
+ }
}
http://git-wip-us.apache.org/repos/asf/hbase/blob/977f8674/hbase-common/src/main/java/org/apache/hadoop/hbase/KeyValue.java
----------------------------------------------------------------------
diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/KeyValue.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/KeyValue.java
index 9857d8c..8835957 100644
--- a/hbase-common/src/main/java/org/apache/hadoop/hbase/KeyValue.java
+++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/KeyValue.java
@@ -95,17 +95,23 @@ public class KeyValue implements Cell, HeapSize, Cloneable, SettableSequenceId,
/**
* Comparator for plain key/values; i.e. non-catalog table key/values. Works on Key portion
* of KeyValue only.
+ * @deprecated Use {@link CellComparator#COMPARATOR} instead
*/
+ @Deprecated
public static final KVComparator COMPARATOR = new KVComparator();
/**
* A {@link KVComparator} for <code>hbase:meta</code> catalog table
* {@link KeyValue}s.
+ * @deprecated Use {@link CellComparator#META_COMPARATOR} instead
*/
+ @Deprecated
public static final KVComparator META_COMPARATOR = new MetaComparator();
/**
* Needed for Bloom Filters.
+ * * @deprecated Use {@link Bytes#BYTES_RAWCOMPARATOR} instead
*/
+ @Deprecated
public static final KVComparator RAW_COMPARATOR = new RawBytesComparator();
/** Size of the key length field in bytes*/
@@ -1061,7 +1067,7 @@ public class KeyValue implements Cell, HeapSize, Cloneable, SettableSequenceId,
if (!(other instanceof Cell)) {
return false;
}
- return CellComparator.equals(this, (Cell)other);
+ return CellUtil.equals(this, (Cell)other);
}
/**
@@ -1069,7 +1075,23 @@ public class KeyValue implements Cell, HeapSize, Cloneable, SettableSequenceId,
*/
@Override
public int hashCode() {
- return CellComparator.hashCodeIgnoreMvcc(this);
+ return calculateHashForKey(this);
+ }
+
+ private int calculateHashForKey(Cell cell) {
+ // pre-calculate the 3 hashes made of byte ranges
+ int rowHash = Bytes.hashCode(cell.getRowArray(), cell.getRowOffset(), cell.getRowLength());
+ int familyHash = Bytes.hashCode(cell.getFamilyArray(), cell.getFamilyOffset(),
+ cell.getFamilyLength());
+ int qualifierHash = Bytes.hashCode(cell.getQualifierArray(), cell.getQualifierOffset(),
+ cell.getQualifierLength());
+
+ // combine the 6 sub-hashes
+ int hash = 31 * rowHash + familyHash;
+ hash = 31 * hash + qualifierHash;
+ hash = 31 * hash + (int) cell.getTimestamp();
+ hash = 31 * hash + cell.getTypeByte();
+ return hash;
}
//---------------------------------------------------------------------------
@@ -1714,7 +1736,9 @@ public class KeyValue implements Cell, HeapSize, Cloneable, SettableSequenceId,
/**
* A {@link KVComparator} for <code>hbase:meta</code> catalog table
* {@link KeyValue}s.
+ * @deprecated : {@link CellComparator#META_COMPARATOR} to be used
*/
+ @Deprecated
public static class MetaComparator extends KVComparator {
/**
* Compare key portion of a {@link KeyValue} for keys in <code>hbase:meta</code>
@@ -1722,11 +1746,7 @@ public class KeyValue implements Cell, HeapSize, Cloneable, SettableSequenceId,
*/
@Override
public int compare(final Cell left, final Cell right) {
- int c = compareRowKey(left, right);
- if (c != 0) {
- return c;
- }
- return CellComparator.compareWithoutRow(left, right);
+ return CellComparator.META_COMPARATOR.compareKeyIgnoresMvcc(left, right);
}
@Override
@@ -1831,7 +1851,9 @@ public class KeyValue implements Cell, HeapSize, Cloneable, SettableSequenceId,
* Compare KeyValues. When we compare KeyValues, we only compare the Key
* portion. This means two KeyValues with same Key but different Values are
* considered the same as far as this Comparator is concerned.
+ * @deprecated : Use {@link CellComparator}.
*/
+ @Deprecated
public static class KVComparator implements RawComparator<Cell>, SamePrefixComparator<byte[]> {
/**
@@ -1857,7 +1879,7 @@ public class KeyValue implements Cell, HeapSize, Cloneable, SettableSequenceId,
* @return 0 if equal, <0 if left smaller, >0 if right smaller
*/
protected int compareRowKey(final Cell left, final Cell right) {
- return CellComparator.compareRows(left, right);
+ return CellComparator.COMPARATOR.compareRows(left, right);
}
/**
@@ -1946,7 +1968,7 @@ public class KeyValue implements Cell, HeapSize, Cloneable, SettableSequenceId,
}
public int compareOnlyKeyPortion(Cell left, Cell right) {
- return CellComparator.compare(left, right, true);
+ return CellComparator.COMPARATOR.compareKeyIgnoresMvcc(left, right);
}
/**
@@ -1955,7 +1977,7 @@ public class KeyValue implements Cell, HeapSize, Cloneable, SettableSequenceId,
*/
@Override
public int compare(final Cell left, final Cell right) {
- int compare = CellComparator.compare(left, right, false);
+ int compare = CellComparator.COMPARATOR.compare(left, right);
return compare;
}
@@ -2269,8 +2291,7 @@ public class KeyValue implements Cell, HeapSize, Cloneable, SettableSequenceId,
* @param leftKey
* @param rightKey
* @return 0 if equal, <0 if left smaller, >0 if right smaller
- * @deprecated Since 0.99.2; Use
- * {@link CellComparator#getMidpoint(KeyValue.KVComparator, Cell, Cell) instead}
+ * @deprecated Since 0.99.2;
*/
@Deprecated
public byte[] getShortMidpointKey(final byte[] leftKey, final byte[] rightKey) {
@@ -2556,8 +2577,9 @@ public class KeyValue implements Cell, HeapSize, Cloneable, SettableSequenceId,
}
/**
- * This is a TEST only Comparator used in TestSeekTo and TestReseekTo.
+ * @deprecated Not to be used for any comparsions
*/
+ @Deprecated
public static class RawBytesComparator extends KVComparator {
/**
* The HFileV2 file format's trailer contains this class name. We reinterpret this and
http://git-wip-us.apache.org/repos/asf/hbase/blob/977f8674/hbase-common/src/main/java/org/apache/hadoop/hbase/KeyValueTestUtil.java
----------------------------------------------------------------------
diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/KeyValueTestUtil.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/KeyValueTestUtil.java
index f0c8b48..50a409d 100644
--- a/hbase-common/src/main/java/org/apache/hadoop/hbase/KeyValueTestUtil.java
+++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/KeyValueTestUtil.java
@@ -85,7 +85,7 @@ public class KeyValueTestUtil {
for (Cell kv1 : kvCollection1) {
boolean found = false;
for (Cell kv2 : kvCollection2) {
- if (CellComparator.equalsIgnoreMvccVersion(kv1, kv2)) found = true;
+ if (CellUtil.equalsIgnoreMvccVersion(kv1, kv2)) found = true;
}
if (!found) return false;
}
http://git-wip-us.apache.org/repos/asf/hbase/blob/977f8674/hbase-common/src/main/java/org/apache/hadoop/hbase/KeyValueUtil.java
----------------------------------------------------------------------
diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/KeyValueUtil.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/KeyValueUtil.java
index 7cbfdd6..4ef14fc 100644
--- a/hbase-common/src/main/java/org/apache/hadoop/hbase/KeyValueUtil.java
+++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/KeyValueUtil.java
@@ -18,7 +18,10 @@
package org.apache.hadoop.hbase;
+import java.io.DataInput;
+import java.io.DataOutput;
import java.io.IOException;
+import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.util.ArrayList;
@@ -31,6 +34,7 @@ import org.apache.hadoop.hbase.util.ByteBufferUtils;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.IterableUtils;
import org.apache.hadoop.hbase.util.SimpleMutableByteRange;
+import org.apache.hadoop.io.IOUtils;
import org.apache.hadoop.io.WritableUtils;
import com.google.common.base.Function;
@@ -541,6 +545,122 @@ public class KeyValueUtil {
});
return new ArrayList<KeyValue>(lazyList);
}
+ /**
+ * Write out a KeyValue in the manner in which we used to when KeyValue was a
+ * Writable.
+ *
+ * @param kv
+ * @param out
+ * @return Length written on stream
+ * @throws IOException
+ * @see #create(DataInput) for the inverse function
+ */
+ public static long write(final KeyValue kv, final DataOutput out) throws IOException {
+ // This is how the old Writables write used to serialize KVs. Need to figure
+ // way to make it
+ // work for all implementations.
+ int length = kv.getLength();
+ out.writeInt(length);
+ out.write(kv.getBuffer(), kv.getOffset(), length);
+ return length + Bytes.SIZEOF_INT;
+ }
+
+ /**
+ * Create a KeyValue reading from the raw InputStream. Named
+ * <code>iscreate</code> so doesn't clash with {@link #create(DataInput)}
+ *
+ * @param in
+ * @return Created KeyValue OR if we find a length of zero, we will return
+ * null which can be useful marking a stream as done.
+ * @throws IOException
+ */
+ public static KeyValue iscreate(final InputStream in) throws IOException {
+ byte[] intBytes = new byte[Bytes.SIZEOF_INT];
+ int bytesRead = 0;
+ while (bytesRead < intBytes.length) {
+ int n = in.read(intBytes, bytesRead, intBytes.length - bytesRead);
+ if (n < 0) {
+ if (bytesRead == 0)
+ return null; // EOF at start is ok
+ throw new IOException("Failed read of int, read " + bytesRead + " bytes");
+ }
+ bytesRead += n;
+ }
+ // TODO: perhaps some sanity check is needed here.
+ byte[] bytes = new byte[Bytes.toInt(intBytes)];
+ IOUtils.readFully(in, bytes, 0, bytes.length);
+ return new KeyValue(bytes, 0, bytes.length);
+ }
+
+ /**
+ * @param b
+ * @return A KeyValue made of a byte array that holds the key-only part.
+ * Needed to convert hfile index members to KeyValues.
+ */
+ public static KeyValue createKeyValueFromKey(final byte[] b) {
+ return createKeyValueFromKey(b, 0, b.length);
+ }
+
+ /**
+ * @param bb
+ * @return A KeyValue made of a byte buffer that holds the key-only part.
+ * Needed to convert hfile index members to KeyValues.
+ */
+ public static KeyValue createKeyValueFromKey(final ByteBuffer bb) {
+ return createKeyValueFromKey(bb.array(), bb.arrayOffset(), bb.limit());
+ }
+
+ /**
+ * @param b
+ * @param o
+ * @param l
+ * @return A KeyValue made of a byte array that holds the key-only part.
+ * Needed to convert hfile index members to KeyValues.
+ */
+ public static KeyValue createKeyValueFromKey(final byte[] b, final int o, final int l) {
+ byte[] newb = new byte[l + KeyValue.ROW_OFFSET];
+ System.arraycopy(b, o, newb, KeyValue.ROW_OFFSET, l);
+ Bytes.putInt(newb, 0, l);
+ Bytes.putInt(newb, Bytes.SIZEOF_INT, 0);
+ return new KeyValue(newb);
+ }
+
+ /**
+ * @param in
+ * Where to read bytes from. Creates a byte array to hold the
+ * KeyValue backing bytes copied from the steam.
+ * @return KeyValue created by deserializing from <code>in</code> OR if we
+ * find a length of zero, we will return null which can be useful
+ * marking a stream as done.
+ * @throws IOException
+ */
+ public static KeyValue create(final DataInput in) throws IOException {
+ return create(in.readInt(), in);
+ }
+
+ /**
+ * Create a KeyValue reading <code>length</code> from <code>in</code>
+ *
+ * @param length
+ * @param in
+ * @return Created KeyValue OR if we find a length of zero, we will return
+ * null which can be useful marking a stream as done.
+ * @throws IOException
+ */
+ public static KeyValue create(int length, final DataInput in) throws IOException {
+
+ if (length <= 0) {
+ if (length == 0)
+ return null;
+ throw new IOException("Failed read " + length + " bytes, stream corrupt?");
+ }
+
+ // This is how the old Writables.readFrom used to deserialize. Didn't even
+ // vint.
+ byte[] bytes = new byte[length];
+ in.readFully(bytes);
+ return new KeyValue(bytes, 0, length);
+ }
public static void oswrite(final Cell cell, final OutputStream out, final boolean withTags)
throws IOException {
@@ -576,7 +696,8 @@ public class KeyValueUtil {
// write tags if we have to
if (withTags && tlen > 0) {
// 2 bytes tags length followed by tags bytes
- // tags length is serialized with 2 bytes only(short way) even if the type is int. As this
+ // tags length is serialized with 2 bytes only(short way) even if the
+ // type is int. As this
// is non -ve numbers, we save the sign bit. See HBASE-11437
out.write((byte) (0xff & (tlen >> 8)));
out.write((byte) (0xff & tlen));
http://git-wip-us.apache.org/repos/asf/hbase/blob/977f8674/hbase-common/src/main/java/org/apache/hadoop/hbase/TableName.java
----------------------------------------------------------------------
diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/TableName.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/TableName.java
index ff86963..0781e1c 100644
--- a/hbase-common/src/main/java/org/apache/hadoop/hbase/TableName.java
+++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/TableName.java
@@ -23,10 +23,10 @@ import java.util.Arrays;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
-import org.apache.hadoop.hbase.KeyValue.KVComparator;
import org.apache.hadoop.hbase.classification.InterfaceAudience;
import org.apache.hadoop.hbase.classification.InterfaceStability;
import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.hadoop.hbase.KeyValue.KVComparator;
/**
* Immutable POJO class for representing a table name.
http://git-wip-us.apache.org/repos/asf/hbase/blob/977f8674/hbase-common/src/main/java/org/apache/hadoop/hbase/codec/KeyValueCodec.java
----------------------------------------------------------------------
diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/codec/KeyValueCodec.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/codec/KeyValueCodec.java
index f41d6b0..7610b30 100644
--- a/hbase-common/src/main/java/org/apache/hadoop/hbase/codec/KeyValueCodec.java
+++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/codec/KeyValueCodec.java
@@ -23,7 +23,6 @@ import java.io.OutputStream;
import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.HBaseInterfaceAudience;
-import org.apache.hadoop.hbase.KeyValue;
import org.apache.hadoop.hbase.KeyValueUtil;
import org.apache.hadoop.hbase.classification.InterfaceAudience;
@@ -65,7 +64,7 @@ public class KeyValueCodec implements Codec {
}
protected Cell parseCell() throws IOException {
- return KeyValue.iscreate(in);
+ return KeyValueUtil.iscreate(in);
}
}