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.DataOutputStream;
22 import java.io.IOException;
23 import java.nio.ByteBuffer;
24 import java.util.Iterator;
25 import java.util.List;
26 import java.util.Map.Entry;
27 import java.util.NavigableMap;
28
29 import org.apache.hadoop.hbase.classification.InterfaceAudience;
30 import org.apache.hadoop.hbase.classification.InterfaceStability;
31 import org.apache.hadoop.hbase.KeyValue.Type;
32 import org.apache.hadoop.hbase.io.HeapSize;
33 import org.apache.hadoop.hbase.util.ByteBufferUtils;
34 import org.apache.hadoop.hbase.util.ByteRange;
35 import org.apache.hadoop.hbase.util.Bytes;
36
37
38
39
40
41
42 @InterfaceAudience.Public
43 @InterfaceStability.Evolving
44 public final class CellUtil {
45
46
47
48 public static ByteRange fillRowRange(Cell cell, ByteRange range) {
49 return range.set(cell.getRowArray(), cell.getRowOffset(), cell.getRowLength());
50 }
51
52 public static ByteRange fillFamilyRange(Cell cell, ByteRange range) {
53 return range.set(cell.getFamilyArray(), cell.getFamilyOffset(), cell.getFamilyLength());
54 }
55
56 public static ByteRange fillQualifierRange(Cell cell, ByteRange range) {
57 return range.set(cell.getQualifierArray(), cell.getQualifierOffset(),
58 cell.getQualifierLength());
59 }
60
61 public static ByteRange fillValueRange(Cell cell, ByteRange range) {
62 return range.set(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength());
63 }
64
65 public static ByteRange fillTagRange(Cell cell, ByteRange range) {
66 return range.set(cell.getTagsArray(), cell.getTagsOffset(), cell.getTagsLength());
67 }
68
69
70
71 public static byte[] cloneRow(Cell cell){
72 byte[] output = new byte[cell.getRowLength()];
73 copyRowTo(cell, output, 0);
74 return output;
75 }
76
77 public static byte[] cloneFamily(Cell cell){
78 byte[] output = new byte[cell.getFamilyLength()];
79 copyFamilyTo(cell, output, 0);
80 return output;
81 }
82
83 public static byte[] cloneQualifier(Cell cell){
84 byte[] output = new byte[cell.getQualifierLength()];
85 copyQualifierTo(cell, output, 0);
86 return output;
87 }
88
89 public static byte[] cloneValue(Cell cell){
90 byte[] output = new byte[cell.getValueLength()];
91 copyValueTo(cell, output, 0);
92 return output;
93 }
94
95
96
97
98
99
100
101
102 public static byte[] getTagArray(Cell cell){
103 byte[] output = new byte[cell.getTagsLength()];
104 copyTagTo(cell, output, 0);
105 return output;
106 }
107
108
109
110
111 public static int copyRowTo(Cell cell, byte[] destination, int destinationOffset) {
112 System.arraycopy(cell.getRowArray(), cell.getRowOffset(), destination, destinationOffset,
113 cell.getRowLength());
114 return destinationOffset + cell.getRowLength();
115 }
116
117 public static int copyFamilyTo(Cell cell, byte[] destination, int destinationOffset) {
118 System.arraycopy(cell.getFamilyArray(), cell.getFamilyOffset(), destination, destinationOffset,
119 cell.getFamilyLength());
120 return destinationOffset + cell.getFamilyLength();
121 }
122
123 public static int copyQualifierTo(Cell cell, byte[] destination, int destinationOffset) {
124 System.arraycopy(cell.getQualifierArray(), cell.getQualifierOffset(), destination,
125 destinationOffset, cell.getQualifierLength());
126 return destinationOffset + cell.getQualifierLength();
127 }
128
129 public static int copyValueTo(Cell cell, byte[] destination, int destinationOffset) {
130 System.arraycopy(cell.getValueArray(), cell.getValueOffset(), destination, destinationOffset,
131 cell.getValueLength());
132 return destinationOffset + cell.getValueLength();
133 }
134
135
136
137
138
139
140
141
142 public static int copyTagTo(Cell cell, byte[] destination, int destinationOffset) {
143 System.arraycopy(cell.getTagsArray(), cell.getTagsOffset(), destination, destinationOffset,
144 cell.getTagsLength());
145 return destinationOffset + cell.getTagsLength();
146 }
147
148
149
150 public static byte getRowByte(Cell cell, int index) {
151 return cell.getRowArray()[cell.getRowOffset() + index];
152 }
153
154 public static ByteBuffer getValueBufferShallowCopy(Cell cell) {
155 ByteBuffer buffer = ByteBuffer.wrap(cell.getValueArray(), cell.getValueOffset(),
156 cell.getValueLength());
157 return buffer;
158 }
159
160 public static ByteBuffer getQualifierBufferShallowCopy(Cell cell) {
161 ByteBuffer buffer = ByteBuffer.wrap(cell.getQualifierArray(), cell.getQualifierOffset(),
162 cell.getQualifierLength());
163 return buffer;
164 }
165
166 public static Cell createCell(final byte [] row, final byte [] family, final byte [] qualifier,
167 final long timestamp, final byte type, final byte [] value) {
168
169
170
171
172 return new KeyValue(row, family, qualifier, timestamp, KeyValue.Type.codeToType(type), value);
173 }
174
175 public static Cell createCell(final byte [] rowArray, final int rowOffset, final int rowLength,
176 final byte [] familyArray, final int familyOffset, final int familyLength,
177 final byte [] qualifierArray, final int qualifierOffset, final int qualifierLength) {
178
179 return new KeyValue(rowArray, rowOffset, rowLength,
180 familyArray, familyOffset, familyLength,
181 qualifierArray, qualifierOffset, qualifierLength,
182 HConstants.LATEST_TIMESTAMP,
183 KeyValue.Type.Maximum,
184 HConstants.EMPTY_BYTE_ARRAY, 0, HConstants.EMPTY_BYTE_ARRAY.length);
185 }
186
187
188
189
190
191
192 @InterfaceAudience.Private
193 public static Cell createCell(final byte[] row, final byte[] family, final byte[] qualifier,
194 final long timestamp, final byte type, final byte[] value, final long memstoreTS) {
195 KeyValue keyValue = new KeyValue(row, family, qualifier, timestamp,
196 KeyValue.Type.codeToType(type), value);
197 keyValue.setSequenceId(memstoreTS);
198 return keyValue;
199 }
200
201
202
203
204
205
206 @InterfaceAudience.Private
207 public static Cell createCell(final byte[] row, final byte[] family, final byte[] qualifier,
208 final long timestamp, final byte type, final byte[] value, byte[] tags, final long memstoreTS) {
209 KeyValue keyValue = new KeyValue(row, family, qualifier, timestamp,
210 KeyValue.Type.codeToType(type), value, tags);
211 keyValue.setSequenceId(memstoreTS);
212 return keyValue;
213 }
214
215
216
217
218
219
220 @InterfaceAudience.Private
221 public static Cell createCell(final byte[] row, final byte[] family, final byte[] qualifier,
222 final long timestamp, Type type, final byte[] value, byte[] tags) {
223 KeyValue keyValue = new KeyValue(row, family, qualifier, timestamp, type, value, tags);
224 return keyValue;
225 }
226
227
228
229
230
231
232 public static Cell createCell(final byte [] row) {
233 return createCell(row, HConstants.EMPTY_BYTE_ARRAY);
234 }
235
236
237
238
239
240
241
242 public static Cell createCell(final byte [] row, final byte [] value) {
243
244
245
246
247 return createCell(row, HConstants.EMPTY_BYTE_ARRAY, HConstants.EMPTY_BYTE_ARRAY,
248 HConstants.LATEST_TIMESTAMP, KeyValue.Type.Maximum.getCode(), value);
249 }
250
251
252
253
254
255
256
257
258 public static Cell createCell(final byte [] row, final byte [] family, final byte [] qualifier) {
259
260 return createCell(row, family, qualifier,
261 HConstants.LATEST_TIMESTAMP, KeyValue.Type.Maximum.getCode(), HConstants.EMPTY_BYTE_ARRAY);
262 }
263
264
265
266
267
268 public static CellScanner createCellScanner(final List<? extends CellScannable> cellScannerables) {
269 return new CellScanner() {
270 private final Iterator<? extends CellScannable> iterator = cellScannerables.iterator();
271 private CellScanner cellScanner = null;
272
273 @Override
274 public Cell current() {
275 return this.cellScanner != null? this.cellScanner.current(): null;
276 }
277
278 @Override
279 public boolean advance() throws IOException {
280 while (true) {
281 if (this.cellScanner == null) {
282 if (!this.iterator.hasNext()) return false;
283 this.cellScanner = this.iterator.next().cellScanner();
284 }
285 if (this.cellScanner.advance()) return true;
286 this.cellScanner = null;
287 }
288 }
289 };
290 }
291
292
293
294
295
296 public static CellScanner createCellScanner(final Iterable<Cell> cellIterable) {
297 if (cellIterable == null) return null;
298 return createCellScanner(cellIterable.iterator());
299 }
300
301
302
303
304
305
306 public static CellScanner createCellScanner(final Iterator<Cell> cells) {
307 if (cells == null) return null;
308 return new CellScanner() {
309 private final Iterator<Cell> iterator = cells;
310 private Cell current = null;
311
312 @Override
313 public Cell current() {
314 return this.current;
315 }
316
317 @Override
318 public boolean advance() {
319 boolean hasNext = this.iterator.hasNext();
320 this.current = hasNext? this.iterator.next(): null;
321 return hasNext;
322 }
323 };
324 }
325
326
327
328
329
330 public static CellScanner createCellScanner(final Cell[] cellArray) {
331 return new CellScanner() {
332 private final Cell [] cells = cellArray;
333 private int index = -1;
334
335 @Override
336 public Cell current() {
337 if (cells == null) return null;
338 return (index < 0)? null: this.cells[index];
339 }
340
341 @Override
342 public boolean advance() {
343 if (cells == null) return false;
344 return ++index < this.cells.length;
345 }
346 };
347 }
348
349
350
351
352
353
354
355 public static CellScanner createCellScanner(final NavigableMap<byte [], List<Cell>> map) {
356 return new CellScanner() {
357 private final Iterator<Entry<byte[], List<Cell>>> entries = map.entrySet().iterator();
358 private Iterator<Cell> currentIterator = null;
359 private Cell currentCell;
360
361 @Override
362 public Cell current() {
363 return this.currentCell;
364 }
365
366 @Override
367 public boolean advance() {
368 while(true) {
369 if (this.currentIterator == null) {
370 if (!this.entries.hasNext()) return false;
371 this.currentIterator = this.entries.next().getValue().iterator();
372 }
373 if (this.currentIterator.hasNext()) {
374 this.currentCell = this.currentIterator.next();
375 return true;
376 }
377 this.currentCell = null;
378 this.currentIterator = null;
379 }
380 }
381 };
382 }
383
384
385
386
387
388
389 public static boolean matchingRow(final Cell left, final Cell right) {
390 return Bytes.equals(left.getRowArray(), left.getRowOffset(), left.getRowLength(),
391 right.getRowArray(), right.getRowOffset(), right.getRowLength());
392 }
393
394 public static boolean matchingRow(final Cell left, final byte[] buf) {
395 return Bytes.equals(left.getRowArray(), left.getRowOffset(), left.getRowLength(), buf, 0,
396 buf.length);
397 }
398
399 public static boolean matchingRow(final Cell left, final byte[] buf, final int offset,
400 final int length) {
401 return Bytes.equals(left.getRowArray(), left.getRowOffset(), left.getRowLength(), buf, offset,
402 length);
403 }
404
405 public static boolean matchingFamily(final Cell left, final Cell right) {
406 return Bytes.equals(left.getFamilyArray(), left.getFamilyOffset(), left.getFamilyLength(),
407 right.getFamilyArray(), right.getFamilyOffset(), right.getFamilyLength());
408 }
409
410 public static boolean matchingFamily(final Cell left, final byte[] buf) {
411 return Bytes.equals(left.getFamilyArray(), left.getFamilyOffset(), left.getFamilyLength(), buf,
412 0, buf.length);
413 }
414
415 public static boolean matchingFamily(final Cell left, final byte[] buf, final int offset,
416 final int length) {
417 return Bytes.equals(left.getFamilyArray(), left.getFamilyOffset(), left.getFamilyLength(), buf,
418 offset, length);
419 }
420
421 public static boolean matchingQualifier(final Cell left, final Cell right) {
422 return Bytes.equals(left.getQualifierArray(), left.getQualifierOffset(),
423 left.getQualifierLength(), right.getQualifierArray(), right.getQualifierOffset(),
424 right.getQualifierLength());
425 }
426
427 public static boolean matchingQualifier(final Cell left, final byte[] buf) {
428 if (buf == null) {
429 return left.getQualifierLength() == 0;
430 }
431 return Bytes.equals(left.getQualifierArray(), left.getQualifierOffset(),
432 left.getQualifierLength(), buf, 0, buf.length);
433 }
434
435 public static boolean matchingQualifier(final Cell left, final byte[] buf, final int offset,
436 final int length) {
437 if (buf == null) {
438 return left.getQualifierLength() == 0;
439 }
440 return Bytes.equals(left.getQualifierArray(), left.getQualifierOffset(),
441 left.getQualifierLength(), buf, offset, length);
442 }
443
444 public static boolean matchingColumn(final Cell left, final byte[] fam, final byte[] qual) {
445 if (!matchingFamily(left, fam))
446 return false;
447 return matchingQualifier(left, qual);
448 }
449
450 public static boolean matchingColumn(final Cell left, final byte[] fam, final int foffset,
451 final int flength, final byte[] qual, final int qoffset, final int qlength) {
452 if (!matchingFamily(left, fam, foffset, flength))
453 return false;
454 return matchingQualifier(left, qual, qoffset, qlength);
455 }
456
457 public static boolean matchingColumn(final Cell left, final Cell right) {
458 if (!matchingFamily(left, right))
459 return false;
460 return matchingQualifier(left, right);
461 }
462
463 public static boolean matchingValue(final Cell left, final Cell right) {
464 return Bytes.equals(left.getValueArray(), left.getValueOffset(), left.getValueLength(),
465 right.getValueArray(), right.getValueOffset(), right.getValueLength());
466 }
467
468 public static boolean matchingValue(final Cell left, final byte[] buf) {
469 return Bytes.equals(left.getValueArray(), left.getValueOffset(), left.getValueLength(), buf, 0,
470 buf.length);
471 }
472
473 public static boolean matchingTimestamp(Cell a, Cell b) {
474 return CellComparator.compareTimestamps(a, b) == 0;
475 }
476
477
478
479
480
481
482
483 public static boolean matchingRowColumn(final Cell left, final Cell right) {
484 if ((left.getRowLength() + left.getFamilyLength() + left.getQualifierLength()) != (right
485 .getRowLength() + right.getFamilyLength() + right.getQualifierLength())) {
486 return false;
487 }
488
489 if (!matchingRow(left, right)) {
490 return false;
491 }
492 return matchingColumn(left, right);
493 }
494
495
496
497
498
499
500 public static boolean isDelete(final Cell cell) {
501 return isDelete(cell.getTypeByte());
502 }
503
504
505
506
507
508
509 public static boolean isDelete(final byte type) {
510 return Type.Delete.getCode() <= type
511 && type <= Type.DeleteFamily.getCode();
512 }
513
514
515
516
517 public static boolean isDeleteType(Cell cell) {
518 return cell.getTypeByte() == Type.Delete.getCode();
519 }
520
521 public static boolean isDeleteFamily(final Cell cell) {
522 return cell.getTypeByte() == Type.DeleteFamily.getCode();
523 }
524
525 public static boolean isDeleteFamilyVersion(final Cell cell) {
526 return cell.getTypeByte() == Type.DeleteFamilyVersion.getCode();
527 }
528
529 public static boolean isDeleteColumns(final Cell cell) {
530 return cell.getTypeByte() == Type.DeleteColumn.getCode();
531 }
532
533 public static boolean isDeleteColumnVersion(final Cell cell) {
534 return cell.getTypeByte() == Type.Delete.getCode();
535 }
536
537
538
539
540
541 public static boolean isDeleteColumnOrFamily(Cell cell) {
542 int t = cell.getTypeByte();
543 return t == Type.DeleteColumn.getCode() || t == Type.DeleteFamily.getCode();
544 }
545
546
547
548
549
550
551
552 @Deprecated
553 public static int estimatedSizeOf(final Cell cell) {
554 return estimatedSerializedSizeOf(cell);
555 }
556
557
558
559
560
561 public static int estimatedSerializedSizeOf(final Cell cell) {
562
563 if (cell instanceof KeyValue) {
564 return ((KeyValue)cell).getLength() + Bytes.SIZEOF_INT;
565 }
566
567
568 return getSumOfCellElementLengths(cell) +
569
570
571 KeyValue.ROW_LENGTH_SIZE + KeyValue.FAMILY_LENGTH_SIZE +
572
573 Bytes.SIZEOF_INT;
574 }
575
576
577
578
579
580 private static int getSumOfCellElementLengths(final Cell cell) {
581 return getSumOfCellKeyElementLengths(cell) + cell.getValueLength() + cell.getTagsLength();
582 }
583
584
585
586
587
588
589 private static int getSumOfCellKeyElementLengths(final Cell cell) {
590 return cell.getRowLength() + cell.getFamilyLength() +
591 cell.getQualifierLength() +
592 KeyValue.TIMESTAMP_TYPE_SIZE;
593 }
594
595
596
597
598
599
600
601 public static int estimatedSerializedSizeOfKey(final Cell cell) {
602 if (cell instanceof KeyValue) return ((KeyValue)cell).getKeyLength();
603 return cell.getRowLength() + cell.getFamilyLength() +
604 cell.getQualifierLength() +
605 KeyValue.KEY_INFRASTRUCTURE_SIZE;
606 }
607
608
609
610
611
612
613
614
615
616 public static long estimatedHeapSizeOf(final Cell cell) {
617 if (cell instanceof HeapSize) {
618 return ((HeapSize) cell).heapSize();
619 }
620
621 return estimatedSerializedSizeOf(cell);
622 }
623
624
625
626
627
628
629
630
631 @Deprecated
632 public static long estimatedHeapSizeOfWithoutTags(final Cell cell) {
633 if (cell instanceof KeyValue) {
634 return ((KeyValue)cell).heapSizeWithoutTags();
635 }
636 return (long) getSumOfCellKeyElementLengths(cell) + cell.getValueLength();
637 }
638
639
640
641
642
643
644
645
646
647
648 public static Iterator<Tag> tagsIterator(final byte[] tags, final int offset, final int length) {
649 return new Iterator<Tag>() {
650 private int pos = offset;
651 private int endOffset = offset + length - 1;
652
653 @Override
654 public boolean hasNext() {
655 return this.pos < endOffset;
656 }
657
658 @Override
659 public Tag next() {
660 if (hasNext()) {
661 int curTagLen = Bytes.readAsInt(tags, this.pos, Tag.TAG_LENGTH_SIZE);
662 Tag tag = new Tag(tags, pos, curTagLen + Tag.TAG_LENGTH_SIZE);
663 this.pos += Bytes.SIZEOF_SHORT + curTagLen;
664 return tag;
665 }
666 return null;
667 }
668
669 @Override
670 public void remove() {
671 throw new UnsupportedOperationException();
672 }
673 };
674 }
675
676
677
678
679
680 public static boolean overlappingKeys(final byte[] start1, final byte[] end1,
681 final byte[] start2, final byte[] end2) {
682 return (end2.length == 0 || start1.length == 0 || Bytes.compareTo(start1,
683 end2) < 0)
684 && (end1.length == 0 || start2.length == 0 || Bytes.compareTo(start2,
685 end1) < 0);
686 }
687
688
689
690
691
692
693
694
695
696 @InterfaceAudience.Private
697 public static void setSequenceId(Cell cell, long seqId) throws IOException {
698 if (cell instanceof SettableSequenceId) {
699 ((SettableSequenceId) cell).setSequenceId(seqId);
700 } else {
701 throw new IOException(new UnsupportedOperationException("Cell is not of type "
702 + SettableSequenceId.class.getName()));
703 }
704 }
705
706
707
708
709
710
711
712 public static void setTimestamp(Cell cell, long ts) throws IOException {
713 if (cell instanceof SettableTimestamp) {
714 ((SettableTimestamp) cell).setTimestamp(ts);
715 } else {
716 throw new IOException(new UnsupportedOperationException("Cell is not of type "
717 + SettableTimestamp.class.getName()));
718 }
719 }
720
721
722
723
724
725
726
727
728 public static void setTimestamp(Cell cell, byte[] ts, int tsOffset) throws IOException {
729 if (cell instanceof SettableTimestamp) {
730 ((SettableTimestamp) cell).setTimestamp(ts, tsOffset);
731 } else {
732 throw new IOException(new UnsupportedOperationException("Cell is not of type "
733 + SettableTimestamp.class.getName()));
734 }
735 }
736
737
738
739
740
741
742
743
744
745 public static boolean updateLatestStamp(Cell cell, long ts) throws IOException {
746 if (cell.getTimestamp() == HConstants.LATEST_TIMESTAMP) {
747 setTimestamp(cell, ts);
748 return true;
749 }
750 return false;
751 }
752
753
754
755
756
757
758
759
760
761
762 public static boolean updateLatestStamp(Cell cell, byte[] ts, int tsOffset) throws IOException {
763 if (cell.getTimestamp() == HConstants.LATEST_TIMESTAMP) {
764 setTimestamp(cell, ts, tsOffset);
765 return true;
766 }
767 return false;
768 }
769
770
771
772
773
774
775
776
777
778 public static void writeFlatKey(Cell cell, DataOutputStream out) throws IOException {
779 short rowLen = cell.getRowLength();
780 out.writeShort(rowLen);
781 out.write(cell.getRowArray(), cell.getRowOffset(), rowLen);
782 byte fLen = cell.getFamilyLength();
783 out.writeByte(fLen);
784 out.write(cell.getFamilyArray(), cell.getFamilyOffset(), fLen);
785 out.write(cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength());
786 out.writeLong(cell.getTimestamp());
787 out.writeByte(cell.getTypeByte());
788 }
789
790
791
792
793
794 public static String getCellKeyAsString(Cell cell) {
795 StringBuilder sb = new StringBuilder(Bytes.toStringBinary(
796 cell.getRowArray(), cell.getRowOffset(), cell.getRowLength()));
797 sb.append('/');
798 sb.append(cell.getFamilyLength() == 0? "":
799 Bytes.toStringBinary(cell.getFamilyArray(), cell.getFamilyOffset(), cell.getFamilyLength()));
800
801 if (cell.getFamilyLength() > 0) sb.append(':');
802 sb.append(cell.getQualifierLength() == 0? "":
803 Bytes.toStringBinary(cell.getQualifierArray(), cell.getQualifierOffset(),
804 cell.getQualifierLength()));
805 sb.append('/');
806 sb.append(KeyValue.humanReadableTimestamp(cell.getTimestamp()));
807 sb.append('/');
808 sb.append(Type.codeToType(cell.getTypeByte()));
809 sb.append("/vlen=");
810 sb.append(cell.getValueLength());
811 sb.append("/seqid=");
812 sb.append(cell.getSequenceId());
813 return sb.toString();
814 }
815
816
817
818
819
820
821
822
823
824 public static byte [] getCellKeySerializedAsKeyValueKey(final Cell cell) {
825 if (cell == null) return null;
826 byte [] b = new byte[KeyValueUtil.keyLength(cell)];
827 KeyValueUtil.appendKeyTo(cell, b, 0);
828 return b;
829 }
830
831
832
833
834
835
836
837
838
839 public static void writeRowKeyExcludingCommon(Cell cell, short rLen, int commonPrefix,
840 DataOutputStream out) throws IOException {
841 if (commonPrefix == 0) {
842 out.writeShort(rLen);
843 } else if (commonPrefix == 1) {
844 out.writeByte((byte) rLen);
845 commonPrefix--;
846 } else {
847 commonPrefix -= KeyValue.ROW_LENGTH_SIZE;
848 }
849 if (rLen > commonPrefix) {
850 out.write(cell.getRowArray(), cell.getRowOffset() + commonPrefix, rLen - commonPrefix);
851 }
852 }
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869 public static int findCommonPrefixInFlatKey(Cell c1, Cell c2, boolean bypassFamilyCheck,
870 boolean withTsType) {
871
872 short rLen1 = c1.getRowLength();
873 short rLen2 = c2.getRowLength();
874 int commonPrefix = KeyValue.ROW_LENGTH_SIZE;
875 if (rLen1 != rLen2) {
876
877 return ByteBufferUtils.findCommonPrefix(Bytes.toBytes(rLen1), 0, KeyValue.ROW_LENGTH_SIZE,
878 Bytes.toBytes(rLen2), 0, KeyValue.ROW_LENGTH_SIZE);
879 }
880
881 int rkCommonPrefix = ByteBufferUtils.findCommonPrefix(c1.getRowArray(), c1.getRowOffset(),
882 rLen1, c2.getRowArray(), c2.getRowOffset(), rLen2);
883 commonPrefix += rkCommonPrefix;
884 if (rkCommonPrefix != rLen1) {
885
886 return commonPrefix;
887 }
888
889 byte fLen1 = c1.getFamilyLength();
890 if (bypassFamilyCheck) {
891
892
893 commonPrefix += KeyValue.FAMILY_LENGTH_SIZE + fLen1;
894 } else {
895 byte fLen2 = c2.getFamilyLength();
896 if (fLen1 != fLen2) {
897
898 return commonPrefix;
899 }
900
901 commonPrefix += KeyValue.FAMILY_LENGTH_SIZE;
902
903 int fCommonPrefix = ByteBufferUtils.findCommonPrefix(c1.getFamilyArray(),
904 c1.getFamilyOffset(), fLen1, c2.getFamilyArray(), c2.getFamilyOffset(), fLen2);
905 commonPrefix += fCommonPrefix;
906 if (fCommonPrefix != fLen1) {
907 return commonPrefix;
908 }
909 }
910
911 int qLen1 = c1.getQualifierLength();
912 int qLen2 = c2.getQualifierLength();
913 int qCommon = ByteBufferUtils.findCommonPrefix(c1.getQualifierArray(), c1.getQualifierOffset(),
914 qLen1, c2.getQualifierArray(), c2.getQualifierOffset(), qLen2);
915 commonPrefix += qCommon;
916 if (!withTsType || Math.max(qLen1, qLen2) != qCommon) {
917 return commonPrefix;
918 }
919
920 int tsCommonPrefix = ByteBufferUtils.findCommonPrefix(Bytes.toBytes(c1.getTimestamp()), 0,
921 KeyValue.TIMESTAMP_SIZE, Bytes.toBytes(c2.getTimestamp()), 0, KeyValue.TIMESTAMP_SIZE);
922 commonPrefix += tsCommonPrefix;
923 if (tsCommonPrefix != KeyValue.TIMESTAMP_SIZE) {
924 return commonPrefix;
925 }
926
927 if (c1.getTypeByte() == c2.getTypeByte()) {
928 commonPrefix += KeyValue.TYPE_SIZE;
929 }
930 return commonPrefix;
931 }
932
933
934 public static String toString(Cell cell, boolean verbose) {
935 if (cell == null) {
936 return "";
937 }
938 StringBuilder builder = new StringBuilder();
939 String keyStr = getCellKeyAsString(cell);
940
941 String tag = null;
942 String value = null;
943 if (verbose) {
944
945 tag = Bytes.toStringBinary(cell.getTagsArray(), cell.getTagsOffset(), cell.getTagsLength());
946 value = Bytes.toStringBinary(cell.getValueArray(), cell.getValueOffset(),
947 cell.getValueLength());
948 }
949
950 builder
951 .append(keyStr);
952 if (tag != null && !tag.isEmpty()) {
953 builder.append("/").append(tag);
954 }
955 if (value != null) {
956 builder.append("/").append(value);
957 }
958
959 return builder.toString();
960 }
961
962
963
964 public static boolean equals(Cell a, Cell b) {
965 return matchingRow(a, b) && matchingFamily(a, b) && matchingQualifier(a, b)
966 && matchingTimestamp(a, b) && matchingType(a, b);
967 }
968
969 public static boolean matchingType(Cell a, Cell b) {
970 return a.getTypeByte() == b.getTypeByte();
971 }
972 }