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 */ 018 019package org.apache.hadoop.hbase; 020 021import java.nio.ByteBuffer; 022import java.util.Comparator; 023 024import org.apache.hadoop.hbase.util.ByteBufferUtils; 025import org.apache.hadoop.hbase.util.Bytes; 026import org.apache.yetus.audience.InterfaceAudience; 027import org.apache.yetus.audience.InterfaceStability; 028 029import org.apache.hbase.thirdparty.com.google.common.primitives.Longs; 030 031/** 032 * A {@link CellComparatorImpl} for <code>hbase:meta</code> catalog table 033 * {@link KeyValue}s. 034 */ 035@InterfaceAudience.Private 036@InterfaceStability.Evolving 037public class MetaCellComparator extends CellComparatorImpl { 038 039 /** 040 * A {@link MetaCellComparator} for <code>hbase:meta</code> catalog table 041 * {@link KeyValue}s. 042 */ 043 public static final MetaCellComparator META_COMPARATOR = new MetaCellComparator(); 044 045 // TODO: Do we need a ByteBufferKeyValue version of this? 046 @Override 047 public int compareRows(final Cell left, final Cell right) { 048 return compareRows(left.getRowArray(), left.getRowOffset(), left.getRowLength(), 049 right.getRowArray(), right.getRowOffset(), right.getRowLength()); 050 } 051 052 @Override 053 public int compareRows(Cell left, byte[] right, int roffset, int rlength) { 054 return compareRows(left.getRowArray(), left.getRowOffset(), left.getRowLength(), right, roffset, 055 rlength); 056 } 057 058 @Override 059 public int compare(final Cell a, final Cell b, boolean ignoreSequenceid) { 060 int diff = compareRows(a, b); 061 if (diff != 0) { 062 return diff; 063 } 064 065 diff = compareWithoutRow(a, b); 066 if (diff != 0) { 067 return diff; 068 } 069 070 // Negate following comparisons so later edits show up first mvccVersion: later sorts first 071 return ignoreSequenceid ? diff : Longs.compare(b.getSequenceId(), a.getSequenceId()); 072 } 073 074 private static int compareRows(byte[] left, int loffset, int llength, byte[] right, int roffset, 075 int rlength) { 076 int leftDelimiter = Bytes.searchDelimiterIndex(left, loffset, llength, HConstants.DELIMITER); 077 int rightDelimiter = Bytes.searchDelimiterIndex(right, roffset, rlength, HConstants.DELIMITER); 078 // Compare up to the delimiter 079 int lpart = (leftDelimiter < 0 ? llength : leftDelimiter - loffset); 080 int rpart = (rightDelimiter < 0 ? rlength : rightDelimiter - roffset); 081 int result = Bytes.compareTo(left, loffset, lpart, right, roffset, rpart); 082 if (result != 0) { 083 return result; 084 } else { 085 if (leftDelimiter < 0 && rightDelimiter >= 0) { 086 return -1; 087 } else if (rightDelimiter < 0 && leftDelimiter >= 0) { 088 return 1; 089 } else if (leftDelimiter < 0) { 090 return 0; 091 } 092 } 093 // Compare middle bit of the row. 094 // Move past delimiter 095 leftDelimiter++; 096 rightDelimiter++; 097 int leftFarDelimiter = Bytes 098 .searchDelimiterIndexInReverse(left, leftDelimiter, llength - (leftDelimiter - loffset), 099 HConstants.DELIMITER); 100 int rightFarDelimiter = Bytes 101 .searchDelimiterIndexInReverse(right, rightDelimiter, rlength - (rightDelimiter - roffset), 102 HConstants.DELIMITER); 103 // Now compare middlesection of row. 104 lpart = (leftFarDelimiter < 0 ? llength + loffset : leftFarDelimiter) - leftDelimiter; 105 rpart = (rightFarDelimiter < 0 ? rlength + roffset : rightFarDelimiter) - rightDelimiter; 106 result = Bytes.compareTo(left, leftDelimiter, lpart, right, rightDelimiter, rpart); 107 if (result != 0) { 108 return result; 109 } else { 110 if (leftDelimiter < 0 && rightDelimiter >= 0) { 111 return -1; 112 } else if (rightDelimiter < 0 && leftDelimiter >= 0) { 113 return 1; 114 } else if (leftDelimiter < 0) { 115 return 0; 116 } 117 } 118 // Compare last part of row, the rowid. 119 leftFarDelimiter++; 120 rightFarDelimiter++; 121 result = Bytes.compareTo(left, leftFarDelimiter, llength - (leftFarDelimiter - loffset), right, 122 rightFarDelimiter, rlength - (rightFarDelimiter - roffset)); 123 return result; 124 } 125 126 @Override 127 public int compareRows(ByteBuffer row, Cell cell) { 128 byte[] array; 129 int offset; 130 int len = row.remaining(); 131 if (row.hasArray()) { 132 array = row.array(); 133 offset = row.position() + row.arrayOffset(); 134 } else { 135 // We copy the row array if offheap just so we can do a compare. We do this elsewhere too 136 // in BBUtils when Cell is backed by an offheap ByteBuffer. Needs fixing so no copy. TODO. 137 array = new byte[len]; 138 offset = 0; 139 ByteBufferUtils.copyFromBufferToArray(array, row, row.position(), 0, len); 140 } 141 // Reverse result since we swap the order of the params we pass below. 142 return -compareRows(cell, array, offset, len); 143 } 144 145 @Override 146 public Comparator getSimpleComparator() { 147 return this; 148 } 149 150}