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 027/** 028 * A {@link CellComparatorImpl} for <code>hbase:meta</code> catalog table {@link KeyValue}s. 029 */ 030@InterfaceAudience.Private 031@InterfaceStability.Evolving 032public class MetaCellComparator extends CellComparatorImpl { 033 034 /** 035 * A {@link MetaCellComparator} for <code>hbase:meta</code> catalog table {@link KeyValue}s. 036 */ 037 public static final MetaCellComparator META_COMPARATOR = new MetaCellComparator(); 038 039 @Override 040 public int compareRows(final Cell left, final Cell right) { 041 if (left instanceof ByteBufferExtendedCell) { 042 ByteBufferExtendedCell bbLeft = (ByteBufferExtendedCell) left; 043 if (right instanceof ByteBufferExtendedCell) { 044 ByteBufferExtendedCell bbRight = (ByteBufferExtendedCell) right; 045 return compareBBRows(bbLeft.getRowByteBuffer(), bbLeft.getRowPosition(), 046 left.getRowLength(), bbRight.getRowByteBuffer(), bbRight.getRowPosition(), 047 right.getRowLength()); 048 } else { 049 return compareBBAndBytesRows(bbLeft.getRowByteBuffer(), bbLeft.getRowPosition(), 050 left.getRowLength(), right.getRowArray(), right.getRowOffset(), right.getRowLength()); 051 } 052 } else { 053 if (right instanceof ByteBufferExtendedCell) { 054 ByteBufferExtendedCell bbRight = (ByteBufferExtendedCell) right; 055 return -compareBBAndBytesRows(bbRight.getRowByteBuffer(), bbRight.getRowPosition(), 056 right.getRowLength(), left.getRowArray(), left.getRowOffset(), left.getRowLength()); 057 } else { 058 return compareBytesRows(left.getRowArray(), left.getRowOffset(), left.getRowLength(), 059 right.getRowArray(), right.getRowOffset(), right.getRowLength()); 060 } 061 } 062 } 063 064 @Override 065 public int compareRows(Cell left, byte[] right, int roffset, int rlength) { 066 if (left instanceof ByteBufferExtendedCell) { 067 ByteBufferExtendedCell bbLeft = (ByteBufferExtendedCell) left; 068 return compareBBAndBytesRows(bbLeft.getRowByteBuffer(), bbLeft.getRowPosition(), 069 left.getRowLength(), right, roffset, rlength); 070 } else { 071 return compareBytesRows(left.getRowArray(), left.getRowOffset(), left.getRowLength(), right, 072 roffset, rlength); 073 } 074 } 075 076 @Override 077 public int compareRows(byte[] leftRow, byte[] rightRow) { 078 return compareBytesRows(leftRow, 0, leftRow.length, rightRow, 0, rightRow.length); 079 } 080 081 @Override 082 public int compare(final Cell a, final Cell b, boolean ignoreSequenceid) { 083 int diff = compareRows(a, b); 084 if (diff != 0) { 085 return diff; 086 } 087 088 diff = compareWithoutRow(a, b); 089 if (diff != 0) { 090 return diff; 091 } 092 093 if (ignoreSequenceid) { 094 return diff; 095 } 096 // Negate following comparisons so later edits show up first mvccVersion: later sorts first 097 return Long.compare(PrivateCellUtil.getSequenceId(b), PrivateCellUtil.getSequenceId(a)); 098 } 099 100 @FunctionalInterface 101 private interface SearchDelimiter<T> { 102 int search(T t, int offset, int length, int delimiter); 103 } 104 105 @FunctionalInterface 106 private interface SearchDelimiterInReverse<T> { 107 int search(T t, int offset, int length, int delimiter); 108 } 109 110 @FunctionalInterface 111 private interface Compare<L, R> { 112 int compareTo(L left, int loffset, int llength, R right, int roffset, int rlength); 113 } 114 115 private static <L, R> int compareRows(L left, int loffset, int llength, R right, int roffset, 116 int rlength, SearchDelimiter<L> searchLeft, SearchDelimiter<R> searchRight, 117 SearchDelimiterInReverse<L> searchInReverseLeft, 118 SearchDelimiterInReverse<R> searchInReverseRight, Compare<L, R> comparator) { 119 int leftDelimiter = searchLeft.search(left, loffset, llength, HConstants.DELIMITER); 120 int rightDelimiter = searchRight.search(right, roffset, rlength, HConstants.DELIMITER); 121 // Compare up to the delimiter 122 int lpart = (leftDelimiter < 0 ? llength : leftDelimiter - loffset); 123 int rpart = (rightDelimiter < 0 ? rlength : rightDelimiter - roffset); 124 int result = comparator.compareTo(left, loffset, lpart, right, roffset, rpart); 125 if (result != 0) { 126 return result; 127 } else { 128 if (leftDelimiter < 0 && rightDelimiter >= 0) { 129 return -1; 130 } else if (rightDelimiter < 0 && leftDelimiter >= 0) { 131 return 1; 132 } else if (leftDelimiter < 0) { 133 return 0; 134 } 135 } 136 // Compare middle bit of the row. 137 // Move past delimiter 138 leftDelimiter++; 139 rightDelimiter++; 140 int leftFarDelimiter = searchInReverseLeft.search(left, leftDelimiter, 141 llength - (leftDelimiter - loffset), HConstants.DELIMITER); 142 int rightFarDelimiter = searchInReverseRight.search(right, rightDelimiter, 143 rlength - (rightDelimiter - roffset), HConstants.DELIMITER); 144 // Now compare middlesection of row. 145 lpart = (leftFarDelimiter < 0 ? llength + loffset : leftFarDelimiter) - leftDelimiter; 146 rpart = (rightFarDelimiter < 0 ? rlength + roffset : rightFarDelimiter) - rightDelimiter; 147 result = comparator.compareTo(left, leftDelimiter, lpart, right, rightDelimiter, rpart); 148 if (result != 0) { 149 return result; 150 } else { 151 if (leftDelimiter < 0 && rightDelimiter >= 0) { 152 return -1; 153 } else if (rightDelimiter < 0 && leftDelimiter >= 0) { 154 return 1; 155 } else if (leftDelimiter < 0) { 156 return 0; 157 } 158 } 159 // Compare last part of row, the rowid. 160 leftFarDelimiter++; 161 rightFarDelimiter++; 162 result = comparator.compareTo(left, leftFarDelimiter, llength - (leftFarDelimiter - loffset), 163 right, rightFarDelimiter, rlength - (rightFarDelimiter - roffset)); 164 return result; 165 } 166 167 private static int compareBBRows(ByteBuffer left, int loffset, int llength, ByteBuffer right, 168 int roffset, int rlength) { 169 if (left.hasArray()) { 170 return -compareBBAndBytesRows(right, roffset, rlength, left.array(), 171 left.arrayOffset() + loffset, llength); 172 } 173 if (right.hasArray()) { 174 return compareBBAndBytesRows(left, loffset, llength, right.array(), 175 right.arrayOffset() + roffset, rlength); 176 } 177 return compareRows(left, loffset, llength, right, roffset, rlength, 178 ByteBufferUtils::searchDelimiterIndex, ByteBufferUtils::searchDelimiterIndex, 179 ByteBufferUtils::searchDelimiterIndexInReverse, 180 ByteBufferUtils::searchDelimiterIndexInReverse, ByteBufferUtils::compareTo); 181 } 182 183 private static int compareBBAndBytesRows(ByteBuffer left, int loffset, int llength, byte[] right, 184 int roffset, int rlength) { 185 if (left.hasArray()) { 186 return compareBytesRows(left.array(), left.arrayOffset() + loffset, llength, right, roffset, 187 rlength); 188 } 189 return compareRows(left, loffset, llength, right, roffset, rlength, 190 ByteBufferUtils::searchDelimiterIndex, Bytes::searchDelimiterIndex, 191 ByteBufferUtils::searchDelimiterIndexInReverse, Bytes::searchDelimiterIndexInReverse, 192 ByteBufferUtils::compareTo); 193 } 194 195 private static int compareBytesRows(byte[] left, int loffset, int llength, byte[] right, 196 int roffset, int rlength) { 197 return compareRows(left, loffset, llength, right, roffset, rlength, Bytes::searchDelimiterIndex, 198 Bytes::searchDelimiterIndex, Bytes::searchDelimiterIndexInReverse, 199 Bytes::searchDelimiterIndexInReverse, Bytes::compareTo); 200 } 201 202 @Override 203 public int compareRows(ByteBuffer row, Cell cell) { 204 if (cell instanceof ByteBufferExtendedCell) { 205 ByteBufferExtendedCell bbCell = (ByteBufferExtendedCell) cell; 206 return compareBBRows(row, row.position(), row.remaining(), bbCell.getRowByteBuffer(), 207 bbCell.getRowPosition(), cell.getRowLength()); 208 } else { 209 return compareBBAndBytesRows(row, row.position(), row.remaining(), cell.getRowArray(), 210 cell.getRowOffset(), cell.getRowLength()); 211 } 212 } 213 214 @Override 215 public Comparator getSimpleComparator() { 216 return this; 217 } 218 219}