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 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 = compareFamilies(left, leftFamilyPosition, leftFamilyLength, right, rightFamilyPosition, 158 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 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 = compareFamilies(left, leftFamilyPosition, leftFamilyLength, right, rightFamilyPosition, 241 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 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 = compareFamilies(left, leftFamilyPosition, leftFamilyLength, right, rightFamilyPosition, 323 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 /** 373 * This method will be overridden when we compare cells inner store to bypass family comparing. 374 */ 375 protected int compareFamilies(Cell left, int leftFamLen, Cell right, int rightFamLen) { 376 if (left instanceof ByteBufferExtendedCell && right instanceof ByteBufferExtendedCell) { 377 return ByteBufferUtils.compareTo(((ByteBufferExtendedCell) left).getFamilyByteBuffer(), 378 ((ByteBufferExtendedCell) left).getFamilyPosition(), leftFamLen, 379 ((ByteBufferExtendedCell) right).getFamilyByteBuffer(), 380 ((ByteBufferExtendedCell) right).getFamilyPosition(), rightFamLen); 381 } 382 if (left instanceof ByteBufferExtendedCell) { 383 return ByteBufferUtils.compareTo(((ByteBufferExtendedCell) left).getFamilyByteBuffer(), 384 ((ByteBufferExtendedCell) left).getFamilyPosition(), leftFamLen, right.getFamilyArray(), 385 right.getFamilyOffset(), rightFamLen); 386 } 387 if (right instanceof ByteBufferExtendedCell) { 388 // Notice how we flip the order of the compare here. We used to negate the return value but 389 // see what FindBugs says 390 // http://findbugs.sourceforge.net/bugDescriptions.html#RV_NEGATING_RESULT_OF_COMPARETO 391 // It suggest flipping the order to get same effect and 'safer'. 392 return ByteBufferUtils.compareTo(left.getFamilyArray(), left.getFamilyOffset(), leftFamLen, 393 ((ByteBufferExtendedCell) right).getFamilyByteBuffer(), 394 ((ByteBufferExtendedCell) right).getFamilyPosition(), rightFamLen); 395 } 396 return Bytes.compareTo(left.getFamilyArray(), left.getFamilyOffset(), leftFamLen, 397 right.getFamilyArray(), right.getFamilyOffset(), rightFamLen); 398 } 399 400 private final int compareQualifiers(Cell left, int leftQualLen, Cell right, int rightQualLen) { 401 if (left instanceof ByteBufferExtendedCell && right instanceof ByteBufferExtendedCell) { 402 return ByteBufferUtils.compareTo(((ByteBufferExtendedCell) left).getQualifierByteBuffer(), 403 ((ByteBufferExtendedCell) left).getQualifierPosition(), leftQualLen, 404 ((ByteBufferExtendedCell) right).getQualifierByteBuffer(), 405 ((ByteBufferExtendedCell) right).getQualifierPosition(), rightQualLen); 406 } 407 if (left instanceof ByteBufferExtendedCell) { 408 return ByteBufferUtils.compareTo(((ByteBufferExtendedCell) left).getQualifierByteBuffer(), 409 ((ByteBufferExtendedCell) left).getQualifierPosition(), leftQualLen, 410 right.getQualifierArray(), right.getQualifierOffset(), rightQualLen); 411 } 412 if (right instanceof ByteBufferExtendedCell) { 413 // Notice how we flip the order of the compare here. We used to negate the return value but 414 // see what FindBugs says 415 // http://findbugs.sourceforge.net/bugDescriptions.html#RV_NEGATING_RESULT_OF_COMPARETO 416 // It suggest flipping the order to get same effect and 'safer'. 417 return ByteBufferUtils.compareTo(left.getQualifierArray(), left.getQualifierOffset(), 418 leftQualLen, ((ByteBufferExtendedCell) right).getQualifierByteBuffer(), 419 ((ByteBufferExtendedCell) right).getQualifierPosition(), rightQualLen); 420 } 421 return Bytes.compareTo(left.getQualifierArray(), left.getQualifierOffset(), leftQualLen, 422 right.getQualifierArray(), right.getQualifierOffset(), rightQualLen); 423 } 424 425 /** 426 * Compare the families of left and right cell 427 * @return 0 if both cells are equal, 1 if left cell is bigger than right, -1 otherwise 428 */ 429 @Override 430 public final int compareFamilies(Cell left, Cell right) { 431 if (left instanceof ByteBufferExtendedCell && right instanceof ByteBufferExtendedCell) { 432 return ByteBufferUtils.compareTo(((ByteBufferExtendedCell) left).getFamilyByteBuffer(), 433 ((ByteBufferExtendedCell) left).getFamilyPosition(), left.getFamilyLength(), 434 ((ByteBufferExtendedCell) right).getFamilyByteBuffer(), 435 ((ByteBufferExtendedCell) right).getFamilyPosition(), right.getFamilyLength()); 436 } 437 if (left instanceof ByteBufferExtendedCell) { 438 return ByteBufferUtils.compareTo(((ByteBufferExtendedCell) left).getFamilyByteBuffer(), 439 ((ByteBufferExtendedCell) left).getFamilyPosition(), left.getFamilyLength(), 440 right.getFamilyArray(), right.getFamilyOffset(), right.getFamilyLength()); 441 } 442 if (right instanceof ByteBufferExtendedCell) { 443 // Notice how we flip the order of the compare here. We used to negate the return value but 444 // see what FindBugs says 445 // http://findbugs.sourceforge.net/bugDescriptions.html#RV_NEGATING_RESULT_OF_COMPARETO 446 // It suggest flipping the order to get same effect and 'safer'. 447 return ByteBufferUtils.compareTo(left.getFamilyArray(), left.getFamilyOffset(), 448 left.getFamilyLength(), ((ByteBufferExtendedCell) right).getFamilyByteBuffer(), 449 ((ByteBufferExtendedCell) right).getFamilyPosition(), right.getFamilyLength()); 450 } 451 return Bytes.compareTo(left.getFamilyArray(), left.getFamilyOffset(), left.getFamilyLength(), 452 right.getFamilyArray(), right.getFamilyOffset(), right.getFamilyLength()); 453 } 454 455 /** 456 * This method will be overridden when we compare cells inner store to bypass family comparing. 457 */ 458 protected int compareFamilies(KeyValue left, int leftFamilyPosition, int leftFamilyLength, 459 KeyValue right, int rightFamilyPosition, int rightFamilyLength) { 460 return Bytes.compareTo(left.getFamilyArray(), leftFamilyPosition, leftFamilyLength, 461 right.getFamilyArray(), rightFamilyPosition, rightFamilyLength); 462 } 463 464 /** 465 * This method will be overridden when we compare cells inner store to bypass family comparing. 466 */ 467 protected int compareFamilies(ByteBufferKeyValue left, int leftFamilyPosition, 468 int leftFamilyLength, ByteBufferKeyValue right, int rightFamilyPosition, 469 int rightFamilyLength) { 470 return ByteBufferUtils.compareTo(left.getFamilyByteBuffer(), leftFamilyPosition, 471 leftFamilyLength, right.getFamilyByteBuffer(), rightFamilyPosition, rightFamilyLength); 472 } 473 474 /** 475 * This method will be overridden when we compare cells inner store to bypass family comparing. 476 */ 477 protected int compareFamilies(KeyValue left, int leftFamilyPosition, int leftFamilyLength, 478 ByteBufferKeyValue right, int rightFamilyPosition, int rightFamilyLength) { 479 return ByteBufferUtils.compareTo(left.getFamilyArray(), leftFamilyPosition, leftFamilyLength, 480 right.getFamilyByteBuffer(), rightFamilyPosition, rightFamilyLength); 481 } 482 483 static int compareQualifiers(KeyValue left, KeyValue right) { 484 // NOTE: Same method is in CellComparatorImpl, also private, not shared, intentionally. Not 485 // sharing gets us a few percent more throughput in compares. If changes here or there, make 486 // sure done in both places. 487 // Compare Rows. Cache row length. 488 int leftRowLength = left.getRowLength(); 489 int rightRowLength = right.getRowLength(); 490 491 int leftFamilyLengthPosition = left.getFamilyLengthPosition(leftRowLength); 492 byte leftFamilyLength = left.getFamilyLength(leftFamilyLengthPosition); 493 int leftKeyLength = left.getKeyLength(); 494 int leftQualifierLength = 495 left.getQualifierLength(leftKeyLength, leftRowLength, leftFamilyLength); 496 497 // No need of left row length below here. 498 499 int rightFamilyLengthPosition = right.getFamilyLengthPosition(rightRowLength); 500 byte rightFamilyLength = right.getFamilyLength(rightFamilyLengthPosition); 501 int rightKeyLength = right.getKeyLength(); 502 int rightQualifierLength = 503 right.getQualifierLength(rightKeyLength, rightRowLength, rightFamilyLength); 504 505 // Compare families. 506 int leftFamilyOffset = left.getFamilyOffset(leftFamilyLengthPosition); 507 int rightFamilyOffset = right.getFamilyOffset(rightFamilyLengthPosition); 508 509 // Compare qualifiers 510 return Bytes.compareTo(left.getQualifierArray(), leftFamilyOffset + leftFamilyLength, 511 leftQualifierLength, right.getQualifierArray(), rightFamilyOffset + rightFamilyLength, 512 rightQualifierLength); 513 } 514 515 static int compareQualifiers(KeyValue left, ByteBufferKeyValue right) { 516 // NOTE: Same method is in CellComparatorImpl, also private, not shared, intentionally. Not 517 // sharing gets us a few percent more throughput in compares. If changes here or there, make 518 // sure done in both places. 519 // Compare Rows. Cache row length. 520 int leftRowLength = left.getRowLength(); 521 int rightRowLength = right.getRowLength(); 522 523 int leftFamilyLengthPosition = left.getFamilyLengthPosition(leftRowLength); 524 byte leftFamilyLength = left.getFamilyLength(leftFamilyLengthPosition); 525 int leftKeyLength = left.getKeyLength(); 526 int leftQualifierLength = 527 left.getQualifierLength(leftKeyLength, leftRowLength, leftFamilyLength); 528 529 // No need of left row length below here. 530 531 int rightFamilyLengthPosition = right.getFamilyLengthPosition(rightRowLength); 532 byte rightFamilyLength = right.getFamilyLength(rightFamilyLengthPosition); 533 int rightKeyLength = right.getKeyLength(); 534 int rightQualifierLength = 535 right.getQualifierLength(rightKeyLength, rightRowLength, rightFamilyLength); 536 537 // Compare families. 538 int leftFamilyOffset = left.getFamilyOffset(leftFamilyLengthPosition); 539 int rightFamilyPosition = right.getFamilyPosition(rightFamilyLengthPosition); 540 541 // Compare qualifiers 542 return ByteBufferUtils.compareTo(left.getQualifierArray(), leftFamilyOffset + leftFamilyLength, 543 leftQualifierLength, right.getQualifierByteBuffer(), rightFamilyPosition + rightFamilyLength, 544 rightQualifierLength); 545 } 546 547 static int compareQualifiers(ByteBufferKeyValue left, KeyValue right) { 548 // NOTE: Same method is in CellComparatorImpl, also private, not shared, intentionally. Not 549 // sharing gets us a few percent more throughput in compares. If changes here or there, make 550 // sure done in both places. 551 // Compare Rows. Cache row length. 552 int leftRowLength = left.getRowLength(); 553 int rightRowLength = right.getRowLength(); 554 555 int leftFamilyLengthPosition = left.getFamilyLengthPosition(leftRowLength); 556 byte leftFamilyLength = left.getFamilyLength(leftFamilyLengthPosition); 557 int leftKeyLength = left.getKeyLength(); 558 int leftQualifierLength = 559 left.getQualifierLength(leftKeyLength, leftRowLength, leftFamilyLength); 560 561 // No need of left row length below here. 562 563 int rightFamilyLengthPosition = right.getFamilyLengthPosition(rightRowLength); 564 byte rightFamilyLength = right.getFamilyLength(rightFamilyLengthPosition); 565 int rightKeyLength = right.getKeyLength(); 566 int rightQualifierLength = 567 right.getQualifierLength(rightKeyLength, rightRowLength, rightFamilyLength); 568 569 // Compare families. 570 int leftFamilyPosition = left.getFamilyPosition(leftFamilyLengthPosition); 571 int rightFamilyOffset = right.getFamilyOffset(rightFamilyLengthPosition); 572 573 // Compare qualifiers 574 return ByteBufferUtils.compareTo(left.getQualifierByteBuffer(), 575 leftFamilyPosition + leftFamilyLength, leftQualifierLength, right.getQualifierArray(), 576 rightFamilyOffset + rightFamilyLength, rightQualifierLength); 577 } 578 579 static int compareQualifiers(ByteBufferKeyValue left, ByteBufferKeyValue right) { 580 // NOTE: Same method is in CellComparatorImpl, also private, not shared, intentionally. Not 581 // sharing gets us a few percent more throughput in compares. If changes here or there, make 582 // sure done in both places. 583 // Compare Rows. Cache row length. 584 int leftRowLength = left.getRowLength(); 585 int rightRowLength = right.getRowLength(); 586 587 int leftFamilyLengthPosition = left.getFamilyLengthPosition(leftRowLength); 588 byte leftFamilyLength = left.getFamilyLength(leftFamilyLengthPosition); 589 int leftKeyLength = left.getKeyLength(); 590 int leftQualifierLength = 591 left.getQualifierLength(leftKeyLength, leftRowLength, leftFamilyLength); 592 593 // No need of left row length below here. 594 595 int rightFamilyLengthPosition = right.getFamilyLengthPosition(rightRowLength); 596 byte rightFamilyLength = right.getFamilyLength(rightFamilyLengthPosition); 597 int rightKeyLength = right.getKeyLength(); 598 int rightQualifierLength = 599 right.getQualifierLength(rightKeyLength, rightRowLength, rightFamilyLength); 600 601 // Compare families. 602 int leftFamilyPosition = left.getFamilyPosition(leftFamilyLengthPosition); 603 int rightFamilyPosition = right.getFamilyPosition(rightFamilyLengthPosition); 604 605 // Compare qualifiers 606 return ByteBufferUtils.compareTo(left.getQualifierByteBuffer(), 607 leftFamilyPosition + leftFamilyLength, leftQualifierLength, right.getQualifierByteBuffer(), 608 rightFamilyPosition + rightFamilyLength, rightQualifierLength); 609 } 610 611 /** 612 * Compare the qualifiers part of the left and right cells. 613 * @return 0 if both cells are equal, 1 if left cell is bigger than right, -1 otherwise 614 */ 615 @Override 616 public final int compareQualifiers(Cell left, Cell right) { 617 if ((left instanceof ByteBufferKeyValue) && (right instanceof ByteBufferKeyValue)) { 618 return compareQualifiers((ByteBufferKeyValue) left, (ByteBufferKeyValue) right); 619 } else if ((left instanceof KeyValue) && (right instanceof KeyValue)) { 620 return compareQualifiers((KeyValue) left, (KeyValue) right); 621 } else if ((left instanceof KeyValue) && (right instanceof ByteBufferKeyValue)) { 622 return compareQualifiers((KeyValue) left, (ByteBufferKeyValue) right); 623 } else if ((left instanceof ByteBufferKeyValue) && (right instanceof KeyValue)) { 624 return compareQualifiers((ByteBufferKeyValue) left, (KeyValue) right); 625 } else { 626 if (left instanceof ByteBufferExtendedCell && right instanceof ByteBufferExtendedCell) { 627 return ByteBufferUtils.compareTo(((ByteBufferExtendedCell) left).getQualifierByteBuffer(), 628 ((ByteBufferExtendedCell) left).getQualifierPosition(), left.getQualifierLength(), 629 ((ByteBufferExtendedCell) right).getQualifierByteBuffer(), 630 ((ByteBufferExtendedCell) right).getQualifierPosition(), right.getQualifierLength()); 631 } 632 if (left instanceof ByteBufferExtendedCell) { 633 return ByteBufferUtils.compareTo(((ByteBufferExtendedCell) left).getQualifierByteBuffer(), 634 ((ByteBufferExtendedCell) left).getQualifierPosition(), left.getQualifierLength(), 635 right.getQualifierArray(), right.getQualifierOffset(), right.getQualifierLength()); 636 } 637 if (right instanceof ByteBufferExtendedCell) { 638 // Notice how we flip the order of the compare here. We used to negate the return value but 639 // see what FindBugs says 640 // http://findbugs.sourceforge.net/bugDescriptions.html#RV_NEGATING_RESULT_OF_COMPARETO 641 // It suggest flipping the order to get same effect and 'safer'. 642 return ByteBufferUtils.compareTo(left.getQualifierArray(), left.getQualifierOffset(), 643 left.getQualifierLength(), ((ByteBufferExtendedCell) right).getQualifierByteBuffer(), 644 ((ByteBufferExtendedCell) right).getQualifierPosition(), right.getQualifierLength()); 645 } 646 return Bytes.compareTo(left.getQualifierArray(), left.getQualifierOffset(), 647 left.getQualifierLength(), right.getQualifierArray(), right.getQualifierOffset(), 648 right.getQualifierLength()); 649 } 650 651 } 652 653 /** 654 * Compares the rows of the left and right cell. For the hbase:meta case this method is overridden 655 * such that it can handle hbase:meta cells. The caller should ensure using the appropriate 656 * comparator for hbase:meta. 657 * @return 0 if both cells are equal, 1 if left cell is bigger than right, -1 otherwise 658 */ 659 @Override 660 public int compareRows(final Cell left, final Cell right) { 661 return compareRows(left, left.getRowLength(), right, right.getRowLength()); 662 } 663 664 static int compareRows(final Cell left, int leftRowLength, final Cell right, int rightRowLength) { 665 // left and right can be exactly the same at the beginning of a row 666 if (left == right) { 667 return 0; 668 } 669 if (left instanceof ByteBufferExtendedCell && right instanceof ByteBufferExtendedCell) { 670 return ByteBufferUtils.compareTo(((ByteBufferExtendedCell) left).getRowByteBuffer(), 671 ((ByteBufferExtendedCell) left).getRowPosition(), leftRowLength, 672 ((ByteBufferExtendedCell) right).getRowByteBuffer(), 673 ((ByteBufferExtendedCell) right).getRowPosition(), rightRowLength); 674 } 675 if (left instanceof ByteBufferExtendedCell) { 676 return ByteBufferUtils.compareTo(((ByteBufferExtendedCell) left).getRowByteBuffer(), 677 ((ByteBufferExtendedCell) left).getRowPosition(), leftRowLength, right.getRowArray(), 678 right.getRowOffset(), rightRowLength); 679 } 680 if (right instanceof ByteBufferExtendedCell) { 681 // Notice how we flip the order of the compare here. We used to negate the return value but 682 // see what FindBugs says 683 // http://findbugs.sourceforge.net/bugDescriptions.html#RV_NEGATING_RESULT_OF_COMPARETO 684 // It suggest flipping the order to get same effect and 'safer'. 685 return ByteBufferUtils.compareTo(left.getRowArray(), left.getRowOffset(), leftRowLength, 686 ((ByteBufferExtendedCell) right).getRowByteBuffer(), 687 ((ByteBufferExtendedCell) right).getRowPosition(), rightRowLength); 688 } 689 return Bytes.compareTo(left.getRowArray(), left.getRowOffset(), leftRowLength, 690 right.getRowArray(), right.getRowOffset(), rightRowLength); 691 } 692 693 /** 694 * Compares the row part of the cell with a simple plain byte[] like the stopRow in Scan. This 695 * should be used with context where for hbase:meta cells the 696 * {{@link MetaCellComparator#META_COMPARATOR} should be used the cell to be compared the kv 697 * serialized byte[] to be compared with the offset in the byte[] the length in the byte[] 698 * @return 0 if both cell and the byte[] are equal, 1 if the cell is bigger than byte[], -1 699 * otherwise 700 */ 701 @Override 702 public int compareRows(Cell left, byte[] right, int roffset, int rlength) { 703 if (left instanceof ByteBufferExtendedCell) { 704 return ByteBufferUtils.compareTo(((ByteBufferExtendedCell) left).getRowByteBuffer(), 705 ((ByteBufferExtendedCell) left).getRowPosition(), left.getRowLength(), right, roffset, 706 rlength); 707 } 708 return Bytes.compareTo(left.getRowArray(), left.getRowOffset(), left.getRowLength(), right, 709 roffset, rlength); 710 } 711 712 @Override 713 public final int compareWithoutRow(final Cell left, final Cell right) { 714 // If the column is not specified, the "minimum" key type appears the 715 // latest in the sorted order, regardless of the timestamp. This is used 716 // for specifying the last key/value in a given row, because there is no 717 // "lexicographically last column" (it would be infinitely long). The 718 // "maximum" key type does not need this behavior. 719 // Copied from KeyValue. This is bad in that we can't do memcmp w/ special rules like this. 720 int lFamLength = left.getFamilyLength(); 721 int rFamLength = right.getFamilyLength(); 722 int lQualLength = left.getQualifierLength(); 723 int rQualLength = right.getQualifierLength(); 724 if (lFamLength + lQualLength == 0 && left.getTypeByte() == KeyValue.Type.Minimum.getCode()) { 725 // left is "bigger", i.e. it appears later in the sorted order 726 return 1; 727 } 728 if (rFamLength + rQualLength == 0 && right.getTypeByte() == KeyValue.Type.Minimum.getCode()) { 729 return -1; 730 } 731 if (lFamLength != rFamLength) { 732 // comparing column family is enough. 733 return compareFamilies(left, lFamLength, right, rFamLength); 734 } 735 // Compare cf:qualifier 736 int diff = compareColumns(left, lFamLength, lQualLength, right, rFamLength, rQualLength); 737 if (diff != 0) { 738 return diff; 739 } 740 741 diff = compareTimestamps(left.getTimestamp(), right.getTimestamp()); 742 if (diff != 0) { 743 return diff; 744 } 745 746 // Compare types. Let the delete types sort ahead of puts; i.e. types 747 // of higher numbers sort before those of lesser numbers. Maximum (255) 748 // appears ahead of everything, and minimum (0) appears after 749 // everything. 750 return (0xff & right.getTypeByte()) - (0xff & left.getTypeByte()); 751 } 752 753 @Override 754 public int compareTimestamps(final Cell left, final Cell right) { 755 return compareTimestamps(left.getTimestamp(), right.getTimestamp()); 756 } 757 758 @Override 759 public int compareTimestamps(final long ltimestamp, final long rtimestamp) { 760 // Swap order we pass into compare so we get DESCENDING order. 761 return Long.compare(rtimestamp, ltimestamp); 762 } 763 764 @Override 765 public Comparator getSimpleComparator() { 766 return this; 767 } 768 769 /** 770 * Utility method that makes a guess at comparator to use based off passed tableName. Use in 771 * extreme when no comparator specified. 772 * @return CellComparator to use going off the {@code tableName} passed. 773 */ 774 public static CellComparator getCellComparator(TableName tableName) { 775 return getCellComparator(tableName.toBytes()); 776 } 777 778 /** 779 * Utility method that makes a guess at comparator to use based off passed tableName. Use in 780 * extreme when no comparator specified. 781 * @return CellComparator to use going off the {@code tableName} passed. 782 */ 783 public static CellComparator getCellComparator(byte[] tableName) { 784 // FYI, TableName.toBytes does not create an array; just returns existing array pointer. 785 return Bytes.equals(tableName, TableName.META_TABLE_NAME.toBytes()) 786 ? MetaCellComparator.META_COMPARATOR 787 : CellComparatorImpl.COMPARATOR; 788 } 789}