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.util.Comparator; 021import org.apache.hadoop.hbase.util.ByteBufferUtils; 022import org.apache.hadoop.hbase.util.Bytes; 023import org.apache.yetus.audience.InterfaceAudience; 024import org.apache.yetus.audience.InterfaceStability; 025 026/** 027 * Compare two HBase cells. Do not use this method comparing <code>-ROOT-</code> or 028 * <code>hbase:meta</code> cells. Cells from these tables need a specialized comparator, one that 029 * takes account of the special formatting of the row where we have commas to delimit table from 030 * regionname, from row. See KeyValue for how it has a special comparator to do hbase:meta cells and 031 * yet another for -ROOT-. 032 * <p> 033 * While using this comparator for {{@link #compareRows(Cell, Cell)} et al, the hbase:meta cells 034 * format should be taken into consideration, for which the instance of this comparator should be 035 * used. In all other cases the static APIs in this comparator would be enough 036 * <p> 037 * HOT methods. We spend a good portion of CPU comparing. Anything that makes the compare faster 038 * will likely manifest at the macro level. See also {@link BBKVComparator}. Use it when mostly 039 * {@link ByteBufferKeyValue}s. 040 * </p> 041 */ 042@edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "UNKNOWN", 043 justification = "Findbugs doesn't like the way we are negating the result of" 044 + " a compare in below") 045@InterfaceAudience.Private 046@InterfaceStability.Evolving 047public class CellComparatorImpl implements CellComparator { 048 049 private static final long serialVersionUID = 8186411895799094989L; 050 051 /** 052 * Comparator for plain key/values; i.e. non-catalog table key/values. Works on Key portion of 053 * KeyValue only. 054 */ 055 public static final CellComparatorImpl COMPARATOR = new CellComparatorImpl(); 056 057 @Override 058 public final int compare(final Cell a, final Cell b) { 059 return compare(a, b, false); 060 } 061 062 @Override 063 public int compare(final Cell l, final Cell r, boolean ignoreSequenceid) { 064 int diff = 0; 065 // "Peel off" the most common path. 066 if (l instanceof KeyValue && r instanceof KeyValue) { 067 diff = compareKeyValues((KeyValue) l, (KeyValue) r); 068 if (diff != 0) { 069 return diff; 070 } 071 } else if (l instanceof KeyValue && r instanceof ByteBufferKeyValue) { 072 diff = compareKVVsBBKV((KeyValue) l, (ByteBufferKeyValue) r); 073 if (diff != 0) { 074 return diff; 075 } 076 } else if (l instanceof ByteBufferKeyValue && r instanceof KeyValue) { 077 diff = compareKVVsBBKV((KeyValue) r, (ByteBufferKeyValue) l); 078 if (diff != 0) { 079 // negate- Findbugs will complain? 080 return -diff; 081 } 082 } else if (l instanceof ByteBufferKeyValue && r instanceof ByteBufferKeyValue) { 083 diff = compareBBKV((ByteBufferKeyValue) l, (ByteBufferKeyValue) r); 084 if (diff != 0) { 085 return diff; 086 } 087 } else { 088 int leftRowLength = l.getRowLength(); 089 int rightRowLength = r.getRowLength(); 090 diff = compareRows(l, leftRowLength, r, rightRowLength); 091 if (diff != 0) { 092 return diff; 093 } 094 095 diff = compareWithoutRow(l, r); 096 if (diff != 0) { 097 return diff; 098 } 099 } 100 // Negate following comparisons so later edits show up first mvccVersion: later sorts first 101 return ignoreSequenceid ? diff : Long.compare(r.getSequenceId(), l.getSequenceId()); 102 } 103 104 private static int compareKeyValues(final KeyValue left, final KeyValue right) { 105 int diff; 106 // Compare Rows. Cache row length. 107 int leftRowLength = left.getRowLength(); 108 int rightRowLength = right.getRowLength(); 109 diff = Bytes.compareTo(left.getRowArray(), left.getRowOffset(), leftRowLength, 110 right.getRowArray(), right.getRowOffset(), rightRowLength); 111 if (diff != 0) { 112 return diff; 113 } 114 115 // If the column is not specified, the "minimum" key type appears as latest in the sorted 116 // order, regardless of the timestamp. This is used for specifying the last key/value in a 117 // given row, because there is no "lexicographically last column" (it would be infinitely 118 // long). 119 // The "maximum" key type does not need this behavior. Copied from KeyValue. This is bad in 120 // that 121 // we can't do memcmp w/ special rules like this. 122 // TODO: Is there a test for this behavior? 123 int leftFamilyLengthPosition = left.getFamilyLengthPosition(leftRowLength); 124 int leftFamilyLength = left.getFamilyLength(leftFamilyLengthPosition); 125 int leftKeyLength = left.getKeyLength(); 126 int leftQualifierLength = 127 left.getQualifierLength(leftKeyLength, leftRowLength, leftFamilyLength); 128 129 // No need of left row length below here. 130 131 byte leftType = left.getTypeByte(leftKeyLength); 132 if ( 133 leftType == KeyValue.Type.Minimum.getCode() && leftFamilyLength + leftQualifierLength == 0 134 ) { 135 // left is "bigger", i.e. it appears later in the sorted order 136 return 1; 137 } 138 139 int rightFamilyLengthPosition = right.getFamilyLengthPosition(rightRowLength); 140 int rightFamilyLength = right.getFamilyLength(rightFamilyLengthPosition); 141 int rightKeyLength = right.getKeyLength(); 142 int rightQualifierLength = 143 right.getQualifierLength(rightKeyLength, rightRowLength, rightFamilyLength); 144 145 // No need of right row length below here. 146 147 byte rightType = right.getTypeByte(rightKeyLength); 148 if ( 149 rightType == KeyValue.Type.Minimum.getCode() && rightFamilyLength + rightQualifierLength == 0 150 ) { 151 return -1; 152 } 153 154 // Compare families. 155 int leftFamilyPosition = left.getFamilyOffset(leftFamilyLengthPosition); 156 int rightFamilyPosition = right.getFamilyOffset(rightFamilyLengthPosition); 157 diff = Bytes.compareTo(left.getFamilyArray(), leftFamilyPosition, leftFamilyLength, 158 right.getFamilyArray(), rightFamilyPosition, rightFamilyLength); 159 if (diff != 0) { 160 return diff; 161 } 162 163 // Compare qualifiers 164 diff = Bytes.compareTo(left.getQualifierArray(), 165 left.getQualifierOffset(leftFamilyPosition, leftFamilyLength), leftQualifierLength, 166 right.getQualifierArray(), right.getQualifierOffset(rightFamilyPosition, rightFamilyLength), 167 rightQualifierLength); 168 if (diff != 0) { 169 return diff; 170 } 171 172 // Timestamps. 173 // Swap order we pass into compare so we get DESCENDING order. 174 // TODO : Ensure we read the bytes and do the compare instead of the value. 175 diff = Long.compare(right.getTimestamp(rightKeyLength), left.getTimestamp(leftKeyLength)); 176 if (diff != 0) { 177 return diff; 178 } 179 180 // Compare types. Let the delete types sort ahead of puts; i.e. types 181 // of higher numbers sort before those of lesser numbers. Maximum (255) 182 // appears ahead of everything, and minimum (0) appears after 183 // everything. 184 return (0xff & rightType) - (0xff & leftType); 185 } 186 187 private static int compareBBKV(final ByteBufferKeyValue left, final ByteBufferKeyValue right) { 188 int diff; 189 // Compare Rows. Cache row length. 190 int leftRowLength = left.getRowLength(); 191 int rightRowLength = right.getRowLength(); 192 diff = ByteBufferUtils.compareTo(left.getRowByteBuffer(), left.getRowPosition(), leftRowLength, 193 right.getRowByteBuffer(), right.getRowPosition(), rightRowLength); 194 if (diff != 0) { 195 return diff; 196 } 197 198 // If the column is not specified, the "minimum" key type appears as latest in the sorted 199 // order, regardless of the timestamp. This is used for specifying the last key/value in a 200 // given row, because there is no "lexicographically last column" (it would be infinitely 201 // long). 202 // The "maximum" key type does not need this behavior. Copied from KeyValue. This is bad in 203 // that 204 // we can't do memcmp w/ special rules like this. 205 // TODO: Is there a test for this behavior? 206 int leftFamilyLengthPosition = left.getFamilyLengthPosition(leftRowLength); 207 int leftFamilyLength = left.getFamilyLength(leftFamilyLengthPosition); 208 int leftKeyLength = left.getKeyLength(); 209 int leftQualifierLength = 210 left.getQualifierLength(leftKeyLength, leftRowLength, leftFamilyLength); 211 212 // No need of left row length below here. 213 214 byte leftType = left.getTypeByte(leftKeyLength); 215 if ( 216 leftType == KeyValue.Type.Minimum.getCode() && leftFamilyLength + leftQualifierLength == 0 217 ) { 218 // left is "bigger", i.e. it appears later in the sorted order 219 return 1; 220 } 221 222 int rightFamilyLengthPosition = right.getFamilyLengthPosition(rightRowLength); 223 int rightFamilyLength = right.getFamilyLength(rightFamilyLengthPosition); 224 int rightKeyLength = right.getKeyLength(); 225 int rightQualifierLength = 226 right.getQualifierLength(rightKeyLength, rightRowLength, rightFamilyLength); 227 228 // No need of right row length below here. 229 230 byte rightType = right.getTypeByte(rightKeyLength); 231 if ( 232 rightType == KeyValue.Type.Minimum.getCode() && rightFamilyLength + rightQualifierLength == 0 233 ) { 234 return -1; 235 } 236 237 // Compare families. 238 int leftFamilyPosition = left.getFamilyPosition(leftFamilyLengthPosition); 239 int rightFamilyPosition = right.getFamilyPosition(rightFamilyLengthPosition); 240 diff = ByteBufferUtils.compareTo(left.getFamilyByteBuffer(), leftFamilyPosition, 241 leftFamilyLength, right.getFamilyByteBuffer(), rightFamilyPosition, rightFamilyLength); 242 if (diff != 0) { 243 return diff; 244 } 245 246 // Compare qualifiers 247 diff = ByteBufferUtils.compareTo(left.getQualifierByteBuffer(), 248 left.getQualifierPosition(leftFamilyPosition, leftFamilyLength), leftQualifierLength, 249 right.getQualifierByteBuffer(), 250 right.getQualifierPosition(rightFamilyPosition, rightFamilyLength), rightQualifierLength); 251 if (diff != 0) { 252 return diff; 253 } 254 255 // Timestamps. 256 // Swap order we pass into compare so we get DESCENDING order. 257 diff = Long.compare(right.getTimestamp(rightKeyLength), left.getTimestamp(leftKeyLength)); 258 if (diff != 0) { 259 return diff; 260 } 261 262 // Compare types. Let the delete types sort ahead of puts; i.e. types 263 // of higher numbers sort before those of lesser numbers. Maximum (255) 264 // appears ahead of everything, and minimum (0) appears after 265 // everything. 266 return (0xff & rightType) - (0xff & leftType); 267 } 268 269 private static int compareKVVsBBKV(final KeyValue left, final ByteBufferKeyValue right) { 270 int diff; 271 // Compare Rows. Cache row length. 272 int leftRowLength = left.getRowLength(); 273 int rightRowLength = right.getRowLength(); 274 diff = ByteBufferUtils.compareTo(left.getRowArray(), left.getRowOffset(), leftRowLength, 275 right.getRowByteBuffer(), right.getRowPosition(), rightRowLength); 276 if (diff != 0) { 277 return diff; 278 } 279 280 // If the column is not specified, the "minimum" key type appears as latest in the sorted 281 // order, regardless of the timestamp. This is used for specifying the last key/value in a 282 // given row, because there is no "lexicographically last column" (it would be infinitely 283 // long). 284 // The "maximum" key type does not need this behavior. Copied from KeyValue. This is bad in 285 // that 286 // we can't do memcmp w/ special rules like this. 287 // TODO: Is there a test for this behavior? 288 int leftFamilyLengthPosition = left.getFamilyLengthPosition(leftRowLength); 289 int leftFamilyLength = left.getFamilyLength(leftFamilyLengthPosition); 290 int leftKeyLength = left.getKeyLength(); 291 int leftQualifierLength = 292 left.getQualifierLength(leftKeyLength, leftRowLength, leftFamilyLength); 293 294 // No need of left row length below here. 295 296 byte leftType = left.getTypeByte(leftKeyLength); 297 if ( 298 leftType == KeyValue.Type.Minimum.getCode() && leftFamilyLength + leftQualifierLength == 0 299 ) { 300 // left is "bigger", i.e. it appears later in the sorted order 301 return 1; 302 } 303 304 int rightFamilyLengthPosition = right.getFamilyLengthPosition(rightRowLength); 305 int rightFamilyLength = right.getFamilyLength(rightFamilyLengthPosition); 306 int rightKeyLength = right.getKeyLength(); 307 int rightQualifierLength = 308 right.getQualifierLength(rightKeyLength, rightRowLength, rightFamilyLength); 309 310 // No need of right row length below here. 311 312 byte rightType = right.getTypeByte(rightKeyLength); 313 if ( 314 rightType == KeyValue.Type.Minimum.getCode() && rightFamilyLength + rightQualifierLength == 0 315 ) { 316 return -1; 317 } 318 319 // Compare families. 320 int leftFamilyPosition = left.getFamilyOffset(leftFamilyLengthPosition); 321 int rightFamilyPosition = right.getFamilyPosition(rightFamilyLengthPosition); 322 diff = ByteBufferUtils.compareTo(left.getFamilyArray(), leftFamilyPosition, leftFamilyLength, 323 right.getFamilyByteBuffer(), rightFamilyPosition, rightFamilyLength); 324 if (diff != 0) { 325 return diff; 326 } 327 328 // Compare qualifiers 329 diff = ByteBufferUtils.compareTo(left.getQualifierArray(), 330 left.getQualifierOffset(leftFamilyPosition, leftFamilyLength), leftQualifierLength, 331 right.getQualifierByteBuffer(), 332 right.getQualifierPosition(rightFamilyPosition, rightFamilyLength), rightQualifierLength); 333 if (diff != 0) { 334 return diff; 335 } 336 337 // Timestamps. 338 // Swap order we pass into compare so we get DESCENDING order. 339 diff = Long.compare(right.getTimestamp(rightKeyLength), left.getTimestamp(leftKeyLength)); 340 if (diff != 0) { 341 return diff; 342 } 343 344 // Compare types. Let the delete types sort ahead of puts; i.e. types 345 // of higher numbers sort before those of lesser numbers. Maximum (255) 346 // appears ahead of everything, and minimum (0) appears after 347 // everything. 348 return (0xff & rightType) - (0xff & leftType); 349 } 350 351 /** 352 * Compares the family and qualifier part of the cell 353 * @return 0 if both cells are equal, 1 if left cell is bigger than right, -1 otherwise 354 */ 355 public final int compareColumns(final Cell left, final Cell right) { 356 int diff = compareFamilies(left, right); 357 if (diff != 0) { 358 return diff; 359 } 360 return compareQualifiers(left, right); 361 } 362 363 private int compareColumns(final Cell left, final int leftFamLen, final int leftQualLen, 364 final Cell right, final int rightFamLen, final int rightQualLen) { 365 int diff = compareFamilies(left, leftFamLen, right, rightFamLen); 366 if (diff != 0) { 367 return diff; 368 } 369 return compareQualifiers(left, leftQualLen, right, rightQualLen); 370 } 371 372 private int compareFamilies(Cell left, int leftFamLen, Cell right, int rightFamLen) { 373 if (left instanceof ByteBufferExtendedCell && right instanceof ByteBufferExtendedCell) { 374 return ByteBufferUtils.compareTo(((ByteBufferExtendedCell) left).getFamilyByteBuffer(), 375 ((ByteBufferExtendedCell) left).getFamilyPosition(), leftFamLen, 376 ((ByteBufferExtendedCell) right).getFamilyByteBuffer(), 377 ((ByteBufferExtendedCell) right).getFamilyPosition(), rightFamLen); 378 } 379 if (left instanceof ByteBufferExtendedCell) { 380 return ByteBufferUtils.compareTo(((ByteBufferExtendedCell) left).getFamilyByteBuffer(), 381 ((ByteBufferExtendedCell) left).getFamilyPosition(), leftFamLen, right.getFamilyArray(), 382 right.getFamilyOffset(), rightFamLen); 383 } 384 if (right instanceof ByteBufferExtendedCell) { 385 // Notice how we flip the order of the compare here. We used to negate the return value but 386 // see what FindBugs says 387 // http://findbugs.sourceforge.net/bugDescriptions.html#RV_NEGATING_RESULT_OF_COMPARETO 388 // It suggest flipping the order to get same effect and 'safer'. 389 return ByteBufferUtils.compareTo(left.getFamilyArray(), left.getFamilyOffset(), leftFamLen, 390 ((ByteBufferExtendedCell) right).getFamilyByteBuffer(), 391 ((ByteBufferExtendedCell) right).getFamilyPosition(), rightFamLen); 392 } 393 return Bytes.compareTo(left.getFamilyArray(), left.getFamilyOffset(), leftFamLen, 394 right.getFamilyArray(), right.getFamilyOffset(), rightFamLen); 395 } 396 397 private final int compareQualifiers(Cell left, int leftQualLen, Cell right, int rightQualLen) { 398 if (left instanceof ByteBufferExtendedCell && right instanceof ByteBufferExtendedCell) { 399 return ByteBufferUtils.compareTo(((ByteBufferExtendedCell) left).getQualifierByteBuffer(), 400 ((ByteBufferExtendedCell) left).getQualifierPosition(), leftQualLen, 401 ((ByteBufferExtendedCell) right).getQualifierByteBuffer(), 402 ((ByteBufferExtendedCell) right).getQualifierPosition(), rightQualLen); 403 } 404 if (left instanceof ByteBufferExtendedCell) { 405 return ByteBufferUtils.compareTo(((ByteBufferExtendedCell) left).getQualifierByteBuffer(), 406 ((ByteBufferExtendedCell) left).getQualifierPosition(), leftQualLen, 407 right.getQualifierArray(), right.getQualifierOffset(), rightQualLen); 408 } 409 if (right instanceof ByteBufferExtendedCell) { 410 // Notice how we flip the order of the compare here. We used to negate the return value but 411 // see what FindBugs says 412 // http://findbugs.sourceforge.net/bugDescriptions.html#RV_NEGATING_RESULT_OF_COMPARETO 413 // It suggest flipping the order to get same effect and 'safer'. 414 return ByteBufferUtils.compareTo(left.getQualifierArray(), left.getQualifierOffset(), 415 leftQualLen, ((ByteBufferExtendedCell) right).getQualifierByteBuffer(), 416 ((ByteBufferExtendedCell) right).getQualifierPosition(), rightQualLen); 417 } 418 return Bytes.compareTo(left.getQualifierArray(), left.getQualifierOffset(), leftQualLen, 419 right.getQualifierArray(), right.getQualifierOffset(), rightQualLen); 420 } 421 422 /** 423 * Compare the families of left and right cell 424 * @return 0 if both cells are equal, 1 if left cell is bigger than right, -1 otherwise 425 */ 426 @Override 427 public final int compareFamilies(Cell left, Cell right) { 428 if (left instanceof ByteBufferExtendedCell && right instanceof ByteBufferExtendedCell) { 429 return ByteBufferUtils.compareTo(((ByteBufferExtendedCell) left).getFamilyByteBuffer(), 430 ((ByteBufferExtendedCell) left).getFamilyPosition(), left.getFamilyLength(), 431 ((ByteBufferExtendedCell) right).getFamilyByteBuffer(), 432 ((ByteBufferExtendedCell) right).getFamilyPosition(), right.getFamilyLength()); 433 } 434 if (left instanceof ByteBufferExtendedCell) { 435 return ByteBufferUtils.compareTo(((ByteBufferExtendedCell) left).getFamilyByteBuffer(), 436 ((ByteBufferExtendedCell) left).getFamilyPosition(), left.getFamilyLength(), 437 right.getFamilyArray(), right.getFamilyOffset(), right.getFamilyLength()); 438 } 439 if (right instanceof ByteBufferExtendedCell) { 440 // Notice how we flip the order of the compare here. We used to negate the return value but 441 // see what FindBugs says 442 // http://findbugs.sourceforge.net/bugDescriptions.html#RV_NEGATING_RESULT_OF_COMPARETO 443 // It suggest flipping the order to get same effect and 'safer'. 444 return ByteBufferUtils.compareTo(left.getFamilyArray(), left.getFamilyOffset(), 445 left.getFamilyLength(), ((ByteBufferExtendedCell) right).getFamilyByteBuffer(), 446 ((ByteBufferExtendedCell) right).getFamilyPosition(), right.getFamilyLength()); 447 } 448 return Bytes.compareTo(left.getFamilyArray(), left.getFamilyOffset(), left.getFamilyLength(), 449 right.getFamilyArray(), right.getFamilyOffset(), right.getFamilyLength()); 450 } 451 452 static int compareQualifiers(KeyValue left, KeyValue right) { 453 // NOTE: Same method is in CellComparatorImpl, also private, not shared, intentionally. Not 454 // sharing gets us a few percent more throughput in compares. If changes here or there, make 455 // sure done in both places. 456 // Compare Rows. Cache row length. 457 int leftRowLength = left.getRowLength(); 458 int rightRowLength = right.getRowLength(); 459 460 int leftFamilyLengthPosition = left.getFamilyLengthPosition(leftRowLength); 461 byte leftFamilyLength = left.getFamilyLength(leftFamilyLengthPosition); 462 int leftKeyLength = left.getKeyLength(); 463 int leftQualifierLength = 464 left.getQualifierLength(leftKeyLength, leftRowLength, leftFamilyLength); 465 466 // No need of left row length below here. 467 468 int rightFamilyLengthPosition = right.getFamilyLengthPosition(rightRowLength); 469 byte rightFamilyLength = right.getFamilyLength(rightFamilyLengthPosition); 470 int rightKeyLength = right.getKeyLength(); 471 int rightQualifierLength = 472 right.getQualifierLength(rightKeyLength, rightRowLength, rightFamilyLength); 473 474 // Compare families. 475 int leftFamilyOffset = left.getFamilyOffset(leftFamilyLengthPosition); 476 int rightFamilyOffset = right.getFamilyOffset(rightFamilyLengthPosition); 477 478 // Compare qualifiers 479 return Bytes.compareTo(left.getQualifierArray(), leftFamilyOffset + leftFamilyLength, 480 leftQualifierLength, right.getQualifierArray(), rightFamilyOffset + rightFamilyLength, 481 rightQualifierLength); 482 } 483 484 static int compareQualifiers(KeyValue left, ByteBufferKeyValue right) { 485 // NOTE: Same method is in CellComparatorImpl, also private, not shared, intentionally. Not 486 // sharing gets us a few percent more throughput in compares. If changes here or there, make 487 // sure done in both places. 488 // Compare Rows. Cache row length. 489 int leftRowLength = left.getRowLength(); 490 int rightRowLength = right.getRowLength(); 491 492 int leftFamilyLengthPosition = left.getFamilyLengthPosition(leftRowLength); 493 byte leftFamilyLength = left.getFamilyLength(leftFamilyLengthPosition); 494 int leftKeyLength = left.getKeyLength(); 495 int leftQualifierLength = 496 left.getQualifierLength(leftKeyLength, leftRowLength, leftFamilyLength); 497 498 // No need of left row length below here. 499 500 int rightFamilyLengthPosition = right.getFamilyLengthPosition(rightRowLength); 501 byte rightFamilyLength = right.getFamilyLength(rightFamilyLengthPosition); 502 int rightKeyLength = right.getKeyLength(); 503 int rightQualifierLength = 504 right.getQualifierLength(rightKeyLength, rightRowLength, rightFamilyLength); 505 506 // Compare families. 507 int leftFamilyOffset = left.getFamilyOffset(leftFamilyLengthPosition); 508 int rightFamilyPosition = right.getFamilyPosition(rightFamilyLengthPosition); 509 510 // Compare qualifiers 511 return ByteBufferUtils.compareTo(left.getQualifierArray(), leftFamilyOffset + leftFamilyLength, 512 leftQualifierLength, right.getQualifierByteBuffer(), rightFamilyPosition + rightFamilyLength, 513 rightQualifierLength); 514 } 515 516 static int compareQualifiers(ByteBufferKeyValue left, KeyValue right) { 517 // NOTE: Same method is in CellComparatorImpl, also private, not shared, intentionally. Not 518 // sharing gets us a few percent more throughput in compares. If changes here or there, make 519 // sure done in both places. 520 // Compare Rows. Cache row length. 521 int leftRowLength = left.getRowLength(); 522 int rightRowLength = right.getRowLength(); 523 524 int leftFamilyLengthPosition = left.getFamilyLengthPosition(leftRowLength); 525 byte leftFamilyLength = left.getFamilyLength(leftFamilyLengthPosition); 526 int leftKeyLength = left.getKeyLength(); 527 int leftQualifierLength = 528 left.getQualifierLength(leftKeyLength, leftRowLength, leftFamilyLength); 529 530 // No need of left row length below here. 531 532 int rightFamilyLengthPosition = right.getFamilyLengthPosition(rightRowLength); 533 byte rightFamilyLength = right.getFamilyLength(rightFamilyLengthPosition); 534 int rightKeyLength = right.getKeyLength(); 535 int rightQualifierLength = 536 right.getQualifierLength(rightKeyLength, rightRowLength, rightFamilyLength); 537 538 // Compare families. 539 int leftFamilyPosition = left.getFamilyPosition(leftFamilyLengthPosition); 540 int rightFamilyOffset = right.getFamilyOffset(rightFamilyLengthPosition); 541 542 // Compare qualifiers 543 return ByteBufferUtils.compareTo(left.getQualifierByteBuffer(), 544 leftFamilyPosition + leftFamilyLength, leftQualifierLength, right.getQualifierArray(), 545 rightFamilyOffset + rightFamilyLength, rightQualifierLength); 546 } 547 548 static int compareQualifiers(ByteBufferKeyValue left, ByteBufferKeyValue right) { 549 // NOTE: Same method is in CellComparatorImpl, also private, not shared, intentionally. Not 550 // sharing gets us a few percent more throughput in compares. If changes here or there, make 551 // sure done in both places. 552 // Compare Rows. Cache row length. 553 int leftRowLength = left.getRowLength(); 554 int rightRowLength = right.getRowLength(); 555 556 int leftFamilyLengthPosition = left.getFamilyLengthPosition(leftRowLength); 557 byte leftFamilyLength = left.getFamilyLength(leftFamilyLengthPosition); 558 int leftKeyLength = left.getKeyLength(); 559 int leftQualifierLength = 560 left.getQualifierLength(leftKeyLength, leftRowLength, leftFamilyLength); 561 562 // No need of left row length below here. 563 564 int rightFamilyLengthPosition = right.getFamilyLengthPosition(rightRowLength); 565 byte rightFamilyLength = right.getFamilyLength(rightFamilyLengthPosition); 566 int rightKeyLength = right.getKeyLength(); 567 int rightQualifierLength = 568 right.getQualifierLength(rightKeyLength, rightRowLength, rightFamilyLength); 569 570 // Compare families. 571 int leftFamilyPosition = left.getFamilyPosition(leftFamilyLengthPosition); 572 int rightFamilyPosition = right.getFamilyPosition(rightFamilyLengthPosition); 573 574 // Compare qualifiers 575 return ByteBufferUtils.compareTo(left.getQualifierByteBuffer(), 576 leftFamilyPosition + leftFamilyLength, leftQualifierLength, right.getQualifierByteBuffer(), 577 rightFamilyPosition + rightFamilyLength, rightQualifierLength); 578 } 579 580 /** 581 * Compare the qualifiers part of the left and right cells. 582 * @return 0 if both cells are equal, 1 if left cell is bigger than right, -1 otherwise 583 */ 584 @Override 585 public final int compareQualifiers(Cell left, Cell right) { 586 if ((left instanceof ByteBufferKeyValue) && (right instanceof ByteBufferKeyValue)) { 587 return compareQualifiers((ByteBufferKeyValue) left, (ByteBufferKeyValue) right); 588 } else if ((left instanceof KeyValue) && (right instanceof KeyValue)) { 589 return compareQualifiers((KeyValue) left, (KeyValue) right); 590 } else if ((left instanceof KeyValue) && (right instanceof ByteBufferKeyValue)) { 591 return compareQualifiers((KeyValue) left, (ByteBufferKeyValue) right); 592 } else if ((left instanceof ByteBufferKeyValue) && (right instanceof KeyValue)) { 593 return compareQualifiers((ByteBufferKeyValue) left, (KeyValue) right); 594 } else { 595 if (left instanceof ByteBufferExtendedCell && right instanceof ByteBufferExtendedCell) { 596 return ByteBufferUtils.compareTo(((ByteBufferExtendedCell) left).getQualifierByteBuffer(), 597 ((ByteBufferExtendedCell) left).getQualifierPosition(), left.getQualifierLength(), 598 ((ByteBufferExtendedCell) right).getQualifierByteBuffer(), 599 ((ByteBufferExtendedCell) right).getQualifierPosition(), right.getQualifierLength()); 600 } 601 if (left instanceof ByteBufferExtendedCell) { 602 return ByteBufferUtils.compareTo(((ByteBufferExtendedCell) left).getQualifierByteBuffer(), 603 ((ByteBufferExtendedCell) left).getQualifierPosition(), left.getQualifierLength(), 604 right.getQualifierArray(), right.getQualifierOffset(), right.getQualifierLength()); 605 } 606 if (right instanceof ByteBufferExtendedCell) { 607 // Notice how we flip the order of the compare here. We used to negate the return value but 608 // see what FindBugs says 609 // http://findbugs.sourceforge.net/bugDescriptions.html#RV_NEGATING_RESULT_OF_COMPARETO 610 // It suggest flipping the order to get same effect and 'safer'. 611 return ByteBufferUtils.compareTo(left.getQualifierArray(), left.getQualifierOffset(), 612 left.getQualifierLength(), ((ByteBufferExtendedCell) right).getQualifierByteBuffer(), 613 ((ByteBufferExtendedCell) right).getQualifierPosition(), right.getQualifierLength()); 614 } 615 return Bytes.compareTo(left.getQualifierArray(), left.getQualifierOffset(), 616 left.getQualifierLength(), right.getQualifierArray(), right.getQualifierOffset(), 617 right.getQualifierLength()); 618 } 619 620 } 621 622 /** 623 * Compares the rows of the left and right cell. For the hbase:meta case this method is overridden 624 * such that it can handle hbase:meta cells. The caller should ensure using the appropriate 625 * comparator for hbase:meta. 626 * @return 0 if both cells are equal, 1 if left cell is bigger than right, -1 otherwise 627 */ 628 @Override 629 public int compareRows(final Cell left, final Cell right) { 630 return compareRows(left, left.getRowLength(), right, right.getRowLength()); 631 } 632 633 static int compareRows(final Cell left, int leftRowLength, final Cell right, int rightRowLength) { 634 // left and right can be exactly the same at the beginning of a row 635 if (left == right) { 636 return 0; 637 } 638 if (left instanceof ByteBufferExtendedCell && right instanceof ByteBufferExtendedCell) { 639 return ByteBufferUtils.compareTo(((ByteBufferExtendedCell) left).getRowByteBuffer(), 640 ((ByteBufferExtendedCell) left).getRowPosition(), leftRowLength, 641 ((ByteBufferExtendedCell) right).getRowByteBuffer(), 642 ((ByteBufferExtendedCell) right).getRowPosition(), rightRowLength); 643 } 644 if (left instanceof ByteBufferExtendedCell) { 645 return ByteBufferUtils.compareTo(((ByteBufferExtendedCell) left).getRowByteBuffer(), 646 ((ByteBufferExtendedCell) left).getRowPosition(), leftRowLength, right.getRowArray(), 647 right.getRowOffset(), rightRowLength); 648 } 649 if (right instanceof ByteBufferExtendedCell) { 650 // Notice how we flip the order of the compare here. We used to negate the return value but 651 // see what FindBugs says 652 // http://findbugs.sourceforge.net/bugDescriptions.html#RV_NEGATING_RESULT_OF_COMPARETO 653 // It suggest flipping the order to get same effect and 'safer'. 654 return ByteBufferUtils.compareTo(left.getRowArray(), left.getRowOffset(), leftRowLength, 655 ((ByteBufferExtendedCell) right).getRowByteBuffer(), 656 ((ByteBufferExtendedCell) right).getRowPosition(), rightRowLength); 657 } 658 return Bytes.compareTo(left.getRowArray(), left.getRowOffset(), leftRowLength, 659 right.getRowArray(), right.getRowOffset(), rightRowLength); 660 } 661 662 /** 663 * Compares the row part of the cell with a simple plain byte[] like the stopRow in Scan. This 664 * should be used with context where for hbase:meta cells the 665 * {{@link MetaCellComparator#META_COMPARATOR} should be used n * the cell to be compared n * the 666 * kv serialized byte[] to be compared with n * the offset in the byte[] n * the length in the 667 * byte[] 668 * @return 0 if both cell and the byte[] are equal, 1 if the cell is bigger than byte[], -1 669 * otherwise 670 */ 671 @Override 672 public int compareRows(Cell left, byte[] right, int roffset, int rlength) { 673 if (left instanceof ByteBufferExtendedCell) { 674 return ByteBufferUtils.compareTo(((ByteBufferExtendedCell) left).getRowByteBuffer(), 675 ((ByteBufferExtendedCell) left).getRowPosition(), left.getRowLength(), right, roffset, 676 rlength); 677 } 678 return Bytes.compareTo(left.getRowArray(), left.getRowOffset(), left.getRowLength(), right, 679 roffset, rlength); 680 } 681 682 @Override 683 public final int compareWithoutRow(final Cell left, final Cell right) { 684 // If the column is not specified, the "minimum" key type appears the 685 // latest in the sorted order, regardless of the timestamp. This is used 686 // for specifying the last key/value in a given row, because there is no 687 // "lexicographically last column" (it would be infinitely long). The 688 // "maximum" key type does not need this behavior. 689 // Copied from KeyValue. This is bad in that we can't do memcmp w/ special rules like this. 690 int lFamLength = left.getFamilyLength(); 691 int rFamLength = right.getFamilyLength(); 692 int lQualLength = left.getQualifierLength(); 693 int rQualLength = right.getQualifierLength(); 694 if (lFamLength + lQualLength == 0 && left.getTypeByte() == KeyValue.Type.Minimum.getCode()) { 695 // left is "bigger", i.e. it appears later in the sorted order 696 return 1; 697 } 698 if (rFamLength + rQualLength == 0 && right.getTypeByte() == KeyValue.Type.Minimum.getCode()) { 699 return -1; 700 } 701 if (lFamLength != rFamLength) { 702 // comparing column family is enough. 703 return compareFamilies(left, lFamLength, right, rFamLength); 704 } 705 // Compare cf:qualifier 706 int diff = compareColumns(left, lFamLength, lQualLength, right, rFamLength, rQualLength); 707 if (diff != 0) { 708 return diff; 709 } 710 711 diff = compareTimestamps(left.getTimestamp(), right.getTimestamp()); 712 if (diff != 0) { 713 return diff; 714 } 715 716 // Compare types. Let the delete types sort ahead of puts; i.e. types 717 // of higher numbers sort before those of lesser numbers. Maximum (255) 718 // appears ahead of everything, and minimum (0) appears after 719 // everything. 720 return (0xff & right.getTypeByte()) - (0xff & left.getTypeByte()); 721 } 722 723 @Override 724 public int compareTimestamps(final Cell left, final Cell right) { 725 return compareTimestamps(left.getTimestamp(), right.getTimestamp()); 726 } 727 728 @Override 729 public int compareTimestamps(final long ltimestamp, final long rtimestamp) { 730 // Swap order we pass into compare so we get DESCENDING order. 731 return Long.compare(rtimestamp, ltimestamp); 732 } 733 734 @Override 735 public Comparator getSimpleComparator() { 736 return this; 737 } 738 739 /** 740 * Utility method that makes a guess at comparator to use based off passed tableName. Use in 741 * extreme when no comparator specified. 742 * @return CellComparator to use going off the {@code tableName} passed. 743 */ 744 public static CellComparator getCellComparator(TableName tableName) { 745 return getCellComparator(tableName.toBytes()); 746 } 747 748 /** 749 * Utility method that makes a guess at comparator to use based off passed tableName. Use in 750 * extreme when no comparator specified. 751 * @return CellComparator to use going off the {@code tableName} passed. 752 */ 753 public static CellComparator getCellComparator(byte[] tableName) { 754 // FYI, TableName.toBytes does not create an array; just returns existing array pointer. 755 return Bytes.equals(tableName, TableName.META_TABLE_NAME.toBytes()) 756 ? MetaCellComparator.META_COMPARATOR 757 : CellComparatorImpl.COMPARATOR; 758 } 759}