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}