1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase;
20
21 import java.io.Serializable;
22 import java.util.Comparator;
23
24 import org.apache.commons.logging.Log;
25 import org.apache.commons.logging.LogFactory;
26 import org.apache.hadoop.hbase.KeyValue.Type;
27 import org.apache.hadoop.hbase.classification.InterfaceAudience;
28 import org.apache.hadoop.hbase.classification.InterfaceStability;
29 import org.apache.hadoop.hbase.filter.ByteArrayComparable;
30 import org.apache.hadoop.hbase.util.ByteBufferUtils;
31 import org.apache.hadoop.hbase.util.Bytes;
32
33 import com.google.common.primitives.Longs;
34
35
36
37
38
39
40
41
42
43
44
45 @edu.umd.cs.findbugs.annotations.SuppressWarnings(
46 value="UNKNOWN",
47 justification="Findbugs doesn't like the way we are negating the result of a compare in below")
48 @InterfaceAudience.Private
49 @InterfaceStability.Evolving
50 public class CellComparator implements Comparator<Cell>, Serializable {
51 static final Log LOG = LogFactory.getLog(CellComparator.class);
52 private static final long serialVersionUID = -8760041766259623329L;
53
54
55
56
57
58 public static final CellComparator COMPARATOR = new CellComparator();
59
60
61
62
63 public static final CellComparator META_COMPARATOR = new MetaCellComparator();
64
65 @Override
66 public int compare(Cell a, Cell b) {
67 return compare(a, b, false);
68 }
69
70
71
72
73
74
75
76
77
78
79 public final int compareKeyIgnoresMvcc(Cell left, Cell right) {
80 return compare(left, right, true);
81 }
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96 public final int compare(Cell left, byte[] key, int offset, int length) {
97
98 short rrowlength = Bytes.toShort(key, offset);
99 int c = compareRows(left, key, offset + Bytes.SIZEOF_SHORT, rrowlength);
100 if (c != 0) return c;
101
102
103
104
105 return compareWithoutRow(left, key, offset, length, rrowlength);
106 }
107
108
109
110
111
112
113
114
115
116 private final int compare(final Cell a, final Cell b, boolean ignoreSequenceid) {
117
118 int c = compareRows(a, b);
119 if (c != 0) return c;
120
121 c = compareWithoutRow(a, b);
122 if(c != 0) return c;
123
124 if (!ignoreSequenceid) {
125
126
127 return Longs.compare(b.getSequenceId(), a.getSequenceId());
128 } else {
129 return c;
130 }
131 }
132
133
134
135
136
137
138
139 public final static int compareColumns(final Cell left, final Cell right) {
140 int diff = compareFamilies(left, right);
141 if (diff != 0) {
142 return diff;
143 }
144 return compareQualifiers(left, right);
145 }
146
147 private final static int compareColumns(Cell left, byte[] right, int rfoffset, int rflength,
148 int rqoffset, int rqlength) {
149 int diff = compareFamilies(left, right, rfoffset, rflength);
150 if (diff != 0)
151 return diff;
152 return compareQualifiers(left, right, rqoffset, rqlength);
153 }
154
155
156
157
158
159
160
161 public final static int compareFamilies(Cell left, Cell right) {
162 if (left instanceof ByteBufferedCell && right instanceof ByteBufferedCell) {
163 return ByteBufferUtils.compareTo(((ByteBufferedCell) left).getFamilyByteBuffer(),
164 ((ByteBufferedCell) left).getFamilyPosition(), left.getFamilyLength(),
165 ((ByteBufferedCell) right).getFamilyByteBuffer(),
166 ((ByteBufferedCell) right).getFamilyPosition(), right.getFamilyLength());
167 }
168 if (left instanceof ByteBufferedCell) {
169 return ByteBufferUtils.compareTo(((ByteBufferedCell) left).getFamilyByteBuffer(),
170 ((ByteBufferedCell) left).getFamilyPosition(), left.getFamilyLength(),
171 right.getFamilyArray(), right.getFamilyOffset(), right.getFamilyLength());
172 }
173 if (right instanceof ByteBufferedCell) {
174 return -(ByteBufferUtils.compareTo(((ByteBufferedCell) right).getFamilyByteBuffer(),
175 ((ByteBufferedCell) right).getFamilyPosition(), right.getFamilyLength(),
176 left.getFamilyArray(), left.getFamilyOffset(), left.getFamilyLength()));
177 }
178 return Bytes.compareTo(left.getFamilyArray(), left.getFamilyOffset(), left.getFamilyLength(),
179 right.getFamilyArray(), right.getFamilyOffset(), right.getFamilyLength());
180 }
181
182 private final static int compareFamilies(Cell left, byte[] right, int roffset, int rlength) {
183 if (left instanceof ByteBufferedCell) {
184 return ByteBufferUtils.compareTo(((ByteBufferedCell) left).getFamilyByteBuffer(),
185 ((ByteBufferedCell) left).getFamilyPosition(), left.getFamilyLength(), right,
186 roffset, rlength);
187 }
188 return Bytes.compareTo(left.getFamilyArray(), left.getFamilyOffset(), left.getFamilyLength(),
189 right, roffset, rlength);
190 }
191
192
193
194
195
196
197
198 public final static int compareQualifiers(Cell left, Cell right) {
199 if (left instanceof ByteBufferedCell && right instanceof ByteBufferedCell) {
200 return ByteBufferUtils
201 .compareTo(((ByteBufferedCell) left).getQualifierByteBuffer(),
202 ((ByteBufferedCell) left).getQualifierPosition(),
203 left.getQualifierLength(), ((ByteBufferedCell) right).getQualifierByteBuffer(),
204 ((ByteBufferedCell) right).getQualifierPosition(),
205 right.getQualifierLength());
206 }
207 if (left instanceof ByteBufferedCell) {
208 return ByteBufferUtils.compareTo(((ByteBufferedCell) left).getQualifierByteBuffer(),
209 ((ByteBufferedCell) left).getQualifierPosition(), left.getQualifierLength(),
210 right.getQualifierArray(), right.getQualifierOffset(), right.getQualifierLength());
211 }
212 if (right instanceof ByteBufferedCell) {
213 return -(ByteBufferUtils.compareTo(((ByteBufferedCell) right).getQualifierByteBuffer(),
214 ((ByteBufferedCell) right).getQualifierPosition(),
215 right.getQualifierLength(), left.getQualifierArray(), left.getQualifierOffset(),
216 left.getQualifierLength()));
217 }
218 return Bytes.compareTo(left.getQualifierArray(), left.getQualifierOffset(),
219 left.getQualifierLength(), right.getQualifierArray(), right.getQualifierOffset(),
220 right.getQualifierLength());
221 }
222
223 public final static int compareQualifiers(Cell left, byte[] right, int rOffset, int rLength) {
224 if (left instanceof ByteBufferedCell) {
225 return ByteBufferUtils.compareTo(((ByteBufferedCell) left).getQualifierByteBuffer(),
226 ((ByteBufferedCell) left).getQualifierPosition(), left.getQualifierLength(),
227 right, rOffset, rLength);
228 }
229 return Bytes.compareTo(left.getQualifierArray(), left.getQualifierOffset(),
230 left.getQualifierLength(), right, rOffset, rLength);
231 }
232
233
234
235
236
237
238
239
240
241
242
243 private final int compareWithoutRow(Cell left,
244 byte[] right, int roffset, int rlength, short rowlength) {
245
246
247
248
249
250 int commonLength = KeyValue.ROW_LENGTH_SIZE + KeyValue.FAMILY_LENGTH_SIZE + rowlength;
251
252
253 int commonLengthWithTSAndType = KeyValue.TIMESTAMP_TYPE_SIZE + commonLength;
254
255 int lcolumnlength = left.getFamilyLength() + left.getQualifierLength();
256 int rcolumnlength = rlength - commonLengthWithTSAndType;
257
258 byte ltype = left.getTypeByte();
259 byte rtype = right[roffset + (rlength - 1)];
260
261
262
263
264
265
266 if (lcolumnlength == 0 && ltype == Type.Minimum.getCode()) {
267
268 return 1;
269 }
270 if (rcolumnlength == 0 && rtype == Type.Minimum.getCode()) {
271 return -1;
272 }
273
274 int rfamilyoffset = commonLength + roffset;
275
276
277 int lfamilylength = left.getFamilyLength();
278 int rfamilylength = right[rfamilyoffset - 1];
279
280
281 boolean sameFamilySize = (lfamilylength == rfamilylength);
282 if (!sameFamilySize) {
283
284 return compareFamilies(left, right, rfamilyoffset, rfamilylength);
285 }
286
287
288 int comparison = compareColumns(left, right, rfamilyoffset, rfamilylength, rfamilyoffset
289 + rfamilylength, (rcolumnlength - rfamilylength));
290 if (comparison != 0) {
291 return comparison;
292 }
293
294
295
296 long rtimestamp = Bytes.toLong(right, roffset + (rlength - KeyValue.TIMESTAMP_TYPE_SIZE));
297 int compare = compareTimestamps(left.getTimestamp(), rtimestamp);
298 if (compare != 0) {
299 return compare;
300 }
301
302
303
304
305
306 return (0xff & rtype) - (0xff & ltype);
307 }
308
309
310
311
312
313
314
315
316
317 public int compareRows(final Cell left, final Cell right) {
318 if (left instanceof ByteBufferedCell && right instanceof ByteBufferedCell) {
319 return ByteBufferUtils.compareTo(((ByteBufferedCell) left).getRowByteBuffer(),
320 ((ByteBufferedCell) left).getRowPosition(), left.getRowLength(),
321 ((ByteBufferedCell) right).getRowByteBuffer(),
322 ((ByteBufferedCell) right).getRowPosition(), right.getRowLength());
323 }
324 if (left instanceof ByteBufferedCell) {
325 return ByteBufferUtils.compareTo(((ByteBufferedCell) left).getRowByteBuffer(),
326 ((ByteBufferedCell) left).getRowPosition(), left.getRowLength(),
327 right.getRowArray(), right.getRowOffset(), right.getRowLength());
328 }
329 if (right instanceof ByteBufferedCell) {
330 return -(ByteBufferUtils.compareTo(((ByteBufferedCell) right).getRowByteBuffer(),
331 ((ByteBufferedCell) right).getRowPosition(), right.getRowLength(),
332 left.getRowArray(), left.getRowOffset(), left.getRowLength()));
333 }
334 return Bytes.compareTo(left.getRowArray(), left.getRowOffset(), left.getRowLength(),
335 right.getRowArray(), right.getRowOffset(), right.getRowLength());
336 }
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354 public int compareRows(Cell left, byte[] right, int roffset, int rlength) {
355 if (left instanceof ByteBufferedCell) {
356 return ByteBufferUtils.compareTo(((ByteBufferedCell) left).getRowByteBuffer(),
357 ((ByteBufferedCell) left).getRowPosition(), left.getRowLength(), right,
358 roffset, rlength);
359 }
360 return Bytes.compareTo(left.getRowArray(), left.getRowOffset(), left.getRowLength(), right,
361 roffset, rlength);
362 }
363
364 private static int compareWithoutRow(final Cell left, final Cell right) {
365
366
367
368
369
370
371 int lFamLength = left.getFamilyLength();
372 int rFamLength = right.getFamilyLength();
373 int lQualLength = left.getQualifierLength();
374 int rQualLength = right.getQualifierLength();
375 if (lFamLength + lQualLength == 0
376 && left.getTypeByte() == Type.Minimum.getCode()) {
377
378 return 1;
379 }
380 if (rFamLength + rQualLength == 0
381 && right.getTypeByte() == Type.Minimum.getCode()) {
382 return -1;
383 }
384 if (lFamLength != rFamLength) {
385
386 return compareFamilies(left, right);
387 }
388
389 int diff = compareColumns(left, right);
390 if (diff != 0) return diff;
391
392 diff = compareTimestamps(left, right);
393 if (diff != 0) return diff;
394
395
396
397
398
399 return (0xff & right.getTypeByte()) - (0xff & left.getTypeByte());
400 }
401
402
403
404
405
406
407
408
409
410
411
412 public static int compareTimestamps(final Cell left, final Cell right) {
413 return compareTimestamps(left.getTimestamp(), right.getTimestamp());
414 }
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436 public final int compareKeyBasedOnColHint(Cell nextIndexedCell, Cell currentCell, int foff,
437 int flen, byte[] colHint, int coff, int clen, long ts, byte type) {
438 int compare = compareRows(nextIndexedCell, currentCell);
439 if (compare != 0) {
440 return compare;
441 }
442
443
444
445
446
447 if (nextIndexedCell.getFamilyLength() + nextIndexedCell.getQualifierLength() == 0
448 && nextIndexedCell.getTypeByte() == Type.Minimum.getCode()) {
449
450 return 1;
451 }
452 if (flen + clen == 0 && type == Type.Minimum.getCode()) {
453 return -1;
454 }
455
456 compare = compareFamilies(nextIndexedCell, currentCell);
457 if (compare != 0) {
458 return compare;
459 }
460 if (colHint == null) {
461 compare = compareQualifiers(nextIndexedCell, currentCell);
462 } else {
463 compare = compareQualifiers(nextIndexedCell, colHint, coff, clen);
464 }
465 if (compare != 0) {
466 return compare;
467 }
468
469 compare = compareTimestamps(nextIndexedCell.getTimestamp(), ts);
470 if (compare != 0) {
471 return compare;
472 }
473
474
475
476
477
478 return (0xff & type) - (0xff & nextIndexedCell.getTypeByte());
479 }
480
481
482
483
484
485
486
487
488
489
490
491 public static int compareTimestamps(final long ltimestamp, final long rtimestamp) {
492 if (ltimestamp < rtimestamp) {
493 return 1;
494 } else if (ltimestamp > rtimestamp) {
495 return -1;
496 }
497 return 0;
498 }
499
500
501
502
503
504
505
506 public static int compareRow(Cell cell, ByteArrayComparable comparator) {
507 if (cell instanceof ByteBufferedCell) {
508 return comparator.compareTo(((ByteBufferedCell) cell).getRowByteBuffer(),
509 ((ByteBufferedCell) cell).getRowPosition(), cell.getRowLength());
510 }
511 return comparator.compareTo(cell.getRowArray(), cell.getRowOffset(), cell.getRowLength());
512 }
513
514
515
516
517
518
519
520 public static int compareFamily(Cell cell, ByteArrayComparable comparator) {
521 if (cell instanceof ByteBufferedCell) {
522 return comparator.compareTo(((ByteBufferedCell) cell).getFamilyByteBuffer(),
523 ((ByteBufferedCell) cell).getFamilyPosition(), cell.getFamilyLength());
524 }
525 return comparator.compareTo(cell.getFamilyArray(), cell.getFamilyOffset(),
526 cell.getFamilyLength());
527 }
528
529
530
531
532
533
534
535 public static int compareQualifier(Cell cell, ByteArrayComparable comparator) {
536 if (cell instanceof ByteBufferedCell) {
537 return comparator.compareTo(((ByteBufferedCell) cell).getQualifierByteBuffer(),
538 ((ByteBufferedCell) cell).getQualifierPosition(), cell.getQualifierLength());
539 }
540 return comparator.compareTo(cell.getQualifierArray(), cell.getQualifierOffset(),
541 cell.getQualifierLength());
542 }
543
544
545
546
547
548
549
550 public static int compareValue(Cell cell, ByteArrayComparable comparator) {
551 if (cell instanceof ByteBufferedCell) {
552 return comparator.compareTo(((ByteBufferedCell) cell).getValueByteBuffer(),
553 ((ByteBufferedCell) cell).getValuePosition(), cell.getValueLength());
554 }
555 return comparator.compareTo(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength());
556 }
557
558
559
560
561 public static class RowComparator extends CellComparator {
562 @Override
563 public int compare(Cell a, Cell b) {
564 return compareRows(a, b);
565 }
566 }
567
568
569
570
571
572 public static class MetaCellComparator extends CellComparator {
573
574 @Override
575 public int compareRows(final Cell left, final Cell right) {
576 return compareRows(left.getRowArray(), left.getRowOffset(), left.getRowLength(),
577 right.getRowArray(), right.getRowOffset(), right.getRowLength());
578 }
579
580 @Override
581 public int compareRows(Cell left, byte[] right, int roffset, int rlength) {
582 return compareRows(left.getRowArray(), left.getRowOffset(), left.getRowLength(), right,
583 roffset, rlength);
584 }
585
586 private int compareRows(byte[] left, int loffset, int llength, byte[] right, int roffset,
587 int rlength) {
588 int leftDelimiter = Bytes.searchDelimiterIndex(left, loffset, llength, HConstants.DELIMITER);
589 int rightDelimiter = Bytes
590 .searchDelimiterIndex(right, roffset, rlength, HConstants.DELIMITER);
591
592 int lpart = (leftDelimiter < 0 ? llength : leftDelimiter - loffset);
593 int rpart = (rightDelimiter < 0 ? rlength : rightDelimiter - roffset);
594 int result = Bytes.compareTo(left, loffset, lpart, right, roffset, rpart);
595 if (result != 0) {
596 return result;
597 } else {
598 if (leftDelimiter < 0 && rightDelimiter >= 0) {
599 return -1;
600 } else if (rightDelimiter < 0 && leftDelimiter >= 0) {
601 return 1;
602 } else if (leftDelimiter < 0 && rightDelimiter < 0) {
603 return 0;
604 }
605 }
606
607
608 leftDelimiter++;
609 rightDelimiter++;
610 int leftFarDelimiter = Bytes.searchDelimiterIndexInReverse(left, leftDelimiter, llength
611 - (leftDelimiter - loffset), HConstants.DELIMITER);
612 int rightFarDelimiter = Bytes.searchDelimiterIndexInReverse(right, rightDelimiter, rlength
613 - (rightDelimiter - roffset), HConstants.DELIMITER);
614
615 lpart = (leftFarDelimiter < 0 ? llength + loffset : leftFarDelimiter) - leftDelimiter;
616 rpart = (rightFarDelimiter < 0 ? rlength + roffset : rightFarDelimiter) - rightDelimiter;
617 result = Bytes.compareTo(left, leftDelimiter, lpart, right, rightDelimiter, rpart);
618 if (result != 0) {
619 return result;
620 } else {
621 if (leftDelimiter < 0 && rightDelimiter >= 0) {
622 return -1;
623 } else if (rightDelimiter < 0 && leftDelimiter >= 0) {
624 return 1;
625 } else if (leftDelimiter < 0 && rightDelimiter < 0) {
626 return 0;
627 }
628 }
629
630 leftFarDelimiter++;
631 rightFarDelimiter++;
632 result = Bytes.compareTo(left, leftFarDelimiter, llength - (leftFarDelimiter - loffset),
633 right, rightFarDelimiter, rlength - (rightFarDelimiter - roffset));
634 return result;
635 }
636 }
637 }