001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase; 019 020import java.nio.ByteBuffer; 021import java.util.Comparator; 022import org.apache.hadoop.hbase.util.ByteBufferUtils; 023import org.apache.hadoop.hbase.util.Bytes; 024import org.apache.yetus.audience.InterfaceAudience; 025import org.apache.yetus.audience.InterfaceStability; 026 027import org.apache.hbase.thirdparty.com.google.common.primitives.Longs; 028 029/** 030 * A {@link CellComparatorImpl} for <code>hbase:meta</code> catalog table {@link KeyValue}s. 031 */ 032@InterfaceAudience.Private 033@InterfaceStability.Evolving 034public class MetaCellComparator extends CellComparatorImpl { 035 036 /** 037 * A {@link MetaCellComparator} for <code>hbase:meta</code> catalog table {@link KeyValue}s. 038 */ 039 public static final MetaCellComparator META_COMPARATOR = new MetaCellComparator(); 040 041 @Override 042 public int compareRows(final Cell left, final Cell right) { 043 if (left instanceof ByteBufferExtendedCell) { 044 ByteBufferExtendedCell bbLeft = (ByteBufferExtendedCell) left; 045 if (right instanceof ByteBufferExtendedCell) { 046 ByteBufferExtendedCell bbRight = (ByteBufferExtendedCell) right; 047 return compareBBRows(bbLeft.getRowByteBuffer(), bbLeft.getRowPosition(), 048 left.getRowLength(), bbRight.getRowByteBuffer(), bbRight.getRowPosition(), 049 right.getRowLength()); 050 } else { 051 return compareBBAndBytesRows(bbLeft.getRowByteBuffer(), bbLeft.getRowPosition(), 052 left.getRowLength(), right.getRowArray(), right.getRowOffset(), right.getRowLength()); 053 } 054 } else { 055 if (right instanceof ByteBufferExtendedCell) { 056 ByteBufferExtendedCell bbRight = (ByteBufferExtendedCell) right; 057 return -compareBBAndBytesRows(bbRight.getRowByteBuffer(), bbRight.getRowPosition(), 058 right.getRowLength(), left.getRowArray(), left.getRowOffset(), left.getRowLength()); 059 } else { 060 return compareBytesRows(left.getRowArray(), left.getRowOffset(), left.getRowLength(), 061 right.getRowArray(), right.getRowOffset(), right.getRowLength()); 062 } 063 } 064 } 065 066 @Override 067 public int compareRows(Cell left, byte[] right, int roffset, int rlength) { 068 if (left instanceof ByteBufferExtendedCell) { 069 ByteBufferExtendedCell bbLeft = (ByteBufferExtendedCell) left; 070 return compareBBAndBytesRows(bbLeft.getRowByteBuffer(), bbLeft.getRowPosition(), 071 left.getRowLength(), right, roffset, rlength); 072 } else { 073 return compareBytesRows(left.getRowArray(), left.getRowOffset(), left.getRowLength(), right, 074 roffset, rlength); 075 } 076 } 077 078 @Override 079 public int compareRows(byte[] leftRow, byte[] rightRow) { 080 return compareBytesRows(leftRow, 0, leftRow.length, rightRow, 0, rightRow.length); 081 } 082 083 @Override 084 public int compare(final Cell a, final Cell b, boolean ignoreSequenceid) { 085 int diff = compareRows(a, b); 086 if (diff != 0) { 087 return diff; 088 } 089 090 diff = compareWithoutRow(a, b); 091 if (diff != 0) { 092 return diff; 093 } 094 095 // Negate following comparisons so later edits show up first mvccVersion: later sorts first 096 return ignoreSequenceid ? diff : Longs.compare(b.getSequenceId(), a.getSequenceId()); 097 } 098 099 @FunctionalInterface 100 private interface SearchDelimiter<T> { 101 int search(T t, int offset, int length, int delimiter); 102 } 103 104 @FunctionalInterface 105 private interface SearchDelimiterInReverse<T> { 106 int search(T t, int offset, int length, int delimiter); 107 } 108 109 @FunctionalInterface 110 private interface Compare<L, R> { 111 int compareTo(L left, int loffset, int llength, R right, int roffset, int rlength); 112 } 113 114 private static <L, R> int compareRows(L left, int loffset, int llength, R right, int roffset, 115 int rlength, SearchDelimiter<L> searchLeft, SearchDelimiter<R> searchRight, 116 SearchDelimiterInReverse<L> searchInReverseLeft, 117 SearchDelimiterInReverse<R> searchInReverseRight, Compare<L, R> comparator) { 118 int leftDelimiter = searchLeft.search(left, loffset, llength, HConstants.DELIMITER); 119 int rightDelimiter = searchRight.search(right, roffset, rlength, HConstants.DELIMITER); 120 // Compare up to the delimiter 121 int lpart = (leftDelimiter < 0 ? llength : leftDelimiter - loffset); 122 int rpart = (rightDelimiter < 0 ? rlength : rightDelimiter - roffset); 123 int result = comparator.compareTo(left, loffset, lpart, right, roffset, rpart); 124 if (result != 0) { 125 return result; 126 } else { 127 if (leftDelimiter < 0 && rightDelimiter >= 0) { 128 return -1; 129 } else if (rightDelimiter < 0 && leftDelimiter >= 0) { 130 return 1; 131 } else if (leftDelimiter < 0) { 132 return 0; 133 } 134 } 135 // Compare middle bit of the row. 136 // Move past delimiter 137 leftDelimiter++; 138 rightDelimiter++; 139 int leftFarDelimiter = searchInReverseLeft.search(left, leftDelimiter, 140 llength - (leftDelimiter - loffset), HConstants.DELIMITER); 141 int rightFarDelimiter = searchInReverseRight.search(right, rightDelimiter, 142 rlength - (rightDelimiter - roffset), HConstants.DELIMITER); 143 // Now compare middlesection of row. 144 lpart = (leftFarDelimiter < 0 ? llength + loffset : leftFarDelimiter) - leftDelimiter; 145 rpart = (rightFarDelimiter < 0 ? rlength + roffset : rightFarDelimiter) - rightDelimiter; 146 result = comparator.compareTo(left, leftDelimiter, lpart, right, rightDelimiter, rpart); 147 if (result != 0) { 148 return result; 149 } else { 150 if (leftDelimiter < 0 && rightDelimiter >= 0) { 151 return -1; 152 } else if (rightDelimiter < 0 && leftDelimiter >= 0) { 153 return 1; 154 } else if (leftDelimiter < 0) { 155 return 0; 156 } 157 } 158 // Compare last part of row, the rowid. 159 leftFarDelimiter++; 160 rightFarDelimiter++; 161 result = comparator.compareTo(left, leftFarDelimiter, llength - (leftFarDelimiter - loffset), 162 right, rightFarDelimiter, rlength - (rightFarDelimiter - roffset)); 163 return result; 164 } 165 166 private static int compareBBRows(ByteBuffer left, int loffset, int llength, ByteBuffer right, 167 int roffset, int rlength) { 168 if (left.hasArray()) { 169 return -compareBBAndBytesRows(right, roffset, rlength, left.array(), 170 left.arrayOffset() + loffset, llength); 171 } 172 if (right.hasArray()) { 173 return compareBBAndBytesRows(left, loffset, llength, right.array(), 174 right.arrayOffset() + roffset, rlength); 175 } 176 return compareRows(left, loffset, llength, right, roffset, rlength, 177 ByteBufferUtils::searchDelimiterIndex, ByteBufferUtils::searchDelimiterIndex, 178 ByteBufferUtils::searchDelimiterIndexInReverse, 179 ByteBufferUtils::searchDelimiterIndexInReverse, ByteBufferUtils::compareTo); 180 } 181 182 private static int compareBBAndBytesRows(ByteBuffer left, int loffset, int llength, byte[] right, 183 int roffset, int rlength) { 184 if (left.hasArray()) { 185 return compareBytesRows(left.array(), left.arrayOffset() + loffset, llength, right, roffset, 186 rlength); 187 } 188 return compareRows(left, loffset, llength, right, roffset, rlength, 189 ByteBufferUtils::searchDelimiterIndex, Bytes::searchDelimiterIndex, 190 ByteBufferUtils::searchDelimiterIndexInReverse, Bytes::searchDelimiterIndexInReverse, 191 ByteBufferUtils::compareTo); 192 } 193 194 private static int compareBytesRows(byte[] left, int loffset, int llength, byte[] right, 195 int roffset, int rlength) { 196 return compareRows(left, loffset, llength, right, roffset, rlength, Bytes::searchDelimiterIndex, 197 Bytes::searchDelimiterIndex, Bytes::searchDelimiterIndexInReverse, 198 Bytes::searchDelimiterIndexInReverse, Bytes::compareTo); 199 } 200 201 @Override 202 public int compareRows(ByteBuffer row, Cell cell) { 203 if (cell instanceof ByteBufferExtendedCell) { 204 ByteBufferExtendedCell bbCell = (ByteBufferExtendedCell) cell; 205 return compareBBRows(row, row.position(), row.remaining(), bbCell.getRowByteBuffer(), 206 bbCell.getRowPosition(), cell.getRowLength()); 207 } else { 208 return compareBBAndBytesRows(row, row.position(), row.remaining(), cell.getRowArray(), 209 cell.getRowOffset(), cell.getRowLength()); 210 } 211 } 212 213 @Override 214 public Comparator getSimpleComparator() { 215 return this; 216 } 217 218}