diff --git hbase-common/src/main/java/org/apache/hadoop/hbase/CellComparator.java hbase-common/src/main/java/org/apache/hadoop/hbase/CellComparator.java index 2e02ad2..d49f3ac 100644 --- hbase-common/src/main/java/org/apache/hadoop/hbase/CellComparator.java +++ hbase-common/src/main/java/org/apache/hadoop/hbase/CellComparator.java @@ -51,9 +51,7 @@ public class CellComparator implements Comparator, Serializable{ public static int compareStatic(Cell a, Cell b) { //row - int c = Bytes.compareTo( - a.getRowArray(), a.getRowOffset(), a.getRowLength(), - b.getRowArray(), b.getRowOffset(), b.getRowLength()); + int c = compareRows(a, b); if (c != 0) return c; // If the column is not specified, the "minimum" key type appears the @@ -69,20 +67,12 @@ public class CellComparator implements Comparator, Serializable{ return -1; } - //family - c = Bytes.compareTo( - a.getFamilyArray(), a.getFamilyOffset(), a.getFamilyLength(), - b.getFamilyArray(), b.getFamilyOffset(), b.getFamilyLength()); - if (c != 0) return c; - - //qualifier - c = Bytes.compareTo( - a.getQualifierArray(), a.getQualifierOffset(), a.getQualifierLength(), - b.getQualifierArray(), b.getQualifierOffset(), b.getQualifierLength()); - if (c != 0) return c; + //family and qualifier + c = compareColumns(a, b); + if(c != 0) return c; //timestamp: later sorts first - c = Longs.compare(b.getTimestamp(), a.getTimestamp()); + c = compareTimestamps(a, b); if (c != 0) return c; //type @@ -129,6 +119,90 @@ public class CellComparator implements Comparator, Serializable{ public static boolean equalsType(Cell a, Cell b){ return a.getTypeByte() == b.getTypeByte(); } + + 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); + } + } + + public int compareFlatKey(Cell left, Cell right) { + int compare = compareRows(left, right); + if (compare != 0) { + return compare; + } + return compareWithoutRow(left, right); + } + + public static int compareRows(final Cell left, final Cell right) { + return Bytes.compareTo(left.getRowArray(), left.getRowOffset(), left.getRowLength(), + right.getRowArray(), right.getRowOffset(), right.getRowLength()); + } + + public static 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) { + if (leftCell.getFamilyLength() + leftCell.getQualifierLength() == 0 + && leftCell.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()) { + return -1; + } + boolean sameFamilySize = (leftCell.getFamilyLength() == rightCell.getFamilyLength()); + if (!sameFamilySize) { + // comparing column family is enough. + + return Bytes.compareTo(leftCell.getFamilyArray(), leftCell.getFamilyOffset(), + leftCell.getFamilyLength(), rightCell.getFamilyArray(), rightCell.getFamilyOffset(), + rightCell.getFamilyLength()); + } + int diff = compareColumns(leftCell, rightCell); + if(diff != 0) { + return diff; + } + + diff = compareTimestamps(leftCell, rightCell); + 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()); + } + + public static int compareTimestamps(final Cell left, final Cell right) { + long ltimestamp = left.getTimestamp(); + long rtimestamp = right.getTimestamp(); + return compareTimestamps(ltimestamp, rtimestamp); + } + + static int compareTimestamps(final long ltimestamp, final long rtimestamp) { + if (ltimestamp < rtimestamp) { + return 1; + } else if (ltimestamp > rtimestamp) { + return -1; + } + return 0; + } /********************* hashCode ************************/ @@ -179,25 +253,15 @@ public class CellComparator implements Comparator, Serializable{ */ private static int compareStaticIgnoreMvccVersion(Cell a, Cell b) { //row - int c = Bytes.compareTo( - a.getRowArray(), a.getRowOffset(), a.getRowLength(), - b.getRowArray(), b.getRowOffset(), b.getRowLength()); + int c = compareRows(a, b); if (c != 0) return c; //family - c = Bytes.compareTo( - a.getFamilyArray(), a.getFamilyOffset(), a.getFamilyLength(), - b.getFamilyArray(), b.getFamilyOffset(), b.getFamilyLength()); - if (c != 0) return c; - - //qualifier - c = Bytes.compareTo( - a.getQualifierArray(), a.getQualifierOffset(), a.getQualifierLength(), - b.getQualifierArray(), b.getQualifierOffset(), b.getQualifierLength()); + c = compareColumns(a, b); if (c != 0) return c; //timestamp: later sorts first - c = Longs.compare(b.getTimestamp(), a.getTimestamp()); + c = compareTimestamps(a, b); if (c != 0) return c; //type @@ -211,5 +275,61 @@ public class CellComparator implements Comparator, Serializable{ public static boolean equalsIgnoreMvccVersion(Cell a, Cell b){ return 0 == compareStaticIgnoreMvccVersion(a, b); } + + /*********************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 compareRowsWithCommonRowPrefix(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 compareRowsWithCommonFamilyPrefix(Cell left, Cell right, int familyCommonPrefix) { + return compare(left.getFamilyArray(), left.getFamilyOffset() + familyCommonPrefix, + left.getFamilyLength() - familyCommonPrefix, right.getFamilyArray(), + right.getFamilyOffset() + familyCommonPrefix, right.getFamilyLength() - familyCommonPrefix); + } + + public static int compareRowsWithQualifierFamilyPrefix(Cell left, Cell right, int qualCommonPrefix) { + return compare(left.getQualifierArray(), left.getQualifierOffset() + qualCommonPrefix, + left.getQualifierLength() - qualCommonPrefix, right.getQualifierArray(), + right.getQualifierOffset() + qualCommonPrefix, right.getQualifierLength() + - qualCommonPrefix); + } + + 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); + } + + 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++; + } + 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); + } + + 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); + } }