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
474
475
476 public static boolean matchingTags(final Cell left, final Cell right) {
477 return Bytes.equals(left.getTagsArray(), left.getTagsOffset(), left.getTagsLength(),
478 right.getTagsArray(), right.getTagsOffset(), right.getTagsLength());
479 }
480
481 public static boolean matchingTimestamp(Cell a, Cell b) {
482 return CellComparator.compareTimestamps(a, b) == 0;
483 }
484
485
486
487
488
489
490
491 public static boolean matchingRowColumn(final Cell left, final Cell right) {
492 if ((left.getRowLength() + left.getFamilyLength() + left.getQualifierLength()) != (right
493 .getRowLength() + right.getFamilyLength() + right.getQualifierLength())) {
494 return false;
495 }
496
497 if (!matchingRow(left, right)) {
498 return false;
499 }
500 return matchingColumn(left, right);
501 }
502
503
504
505
506
507
508 public static boolean isDelete(final Cell cell) {
509 return isDelete(cell.getTypeByte());
510 }
511
512
513
514
515
516
517 public static boolean isDelete(final byte type) {
518 return Type.Delete.getCode() <= type
519 && type <= Type.DeleteFamily.getCode();
520 }
521
522
523
524
525 public static boolean isDeleteType(Cell cell) {
526 return cell.getTypeByte() == Type.Delete.getCode();
527 }
528
529 public static boolean isDeleteFamily(final Cell cell) {
530 return cell.getTypeByte() == Type.DeleteFamily.getCode();
531 }
532
533 public static boolean isDeleteFamilyVersion(final Cell cell) {
534 return cell.getTypeByte() == Type.DeleteFamilyVersion.getCode();
535 }
536
537 public static boolean isDeleteColumns(final Cell cell) {
538 return cell.getTypeByte() == Type.DeleteColumn.getCode();
539 }
540
541 public static boolean isDeleteColumnVersion(final Cell cell) {
542 return cell.getTypeByte() == Type.Delete.getCode();
543 }
544
545
546
547
548
549 public static boolean isDeleteColumnOrFamily(Cell cell) {
550 int t = cell.getTypeByte();
551 return t == Type.DeleteColumn.getCode() || t == Type.DeleteFamily.getCode();
552 }
553
554
555
556
557
558
559
560 @Deprecated
561 public static int estimatedSizeOf(final Cell cell) {
562 return estimatedSerializedSizeOf(cell);
563 }
564
565
566
567
568
569 public static int estimatedSerializedSizeOf(final Cell cell) {
570
571 if (cell instanceof KeyValue) {
572 return ((KeyValue)cell).getLength() + Bytes.SIZEOF_INT;
573 }
574
575
576 return getSumOfCellElementLengths(cell) +
577
578
579 KeyValue.ROW_LENGTH_SIZE + KeyValue.FAMILY_LENGTH_SIZE +
580
581 Bytes.SIZEOF_INT;
582 }
583
584
585
586
587
588 private static int getSumOfCellElementLengths(final Cell cell) {
589 return getSumOfCellKeyElementLengths(cell) + cell.getValueLength() + cell.getTagsLength();
590 }
591
592
593
594
595
596
597 private static int getSumOfCellKeyElementLengths(final Cell cell) {
598 return cell.getRowLength() + cell.getFamilyLength() +
599 cell.getQualifierLength() +
600 KeyValue.TIMESTAMP_TYPE_SIZE;
601 }
602
603
604
605
606
607
608
609 public static int estimatedSerializedSizeOfKey(final Cell cell) {
610 if (cell instanceof KeyValue) return ((KeyValue)cell).getKeyLength();
611 return cell.getRowLength() + cell.getFamilyLength() +
612 cell.getQualifierLength() +
613 KeyValue.KEY_INFRASTRUCTURE_SIZE;
614 }
615
616
617
618
619
620
621
622
623
624 public static long estimatedHeapSizeOf(final Cell cell) {
625 if (cell instanceof HeapSize) {
626 return ((HeapSize) cell).heapSize();
627 }
628
629 return estimatedSerializedSizeOf(cell);
630 }
631
632
633
634
635
636
637
638
639 @Deprecated
640 public static long estimatedHeapSizeOfWithoutTags(final Cell cell) {
641 if (cell instanceof KeyValue) {
642 return ((KeyValue)cell).heapSizeWithoutTags();
643 }
644 return (long) getSumOfCellKeyElementLengths(cell) + cell.getValueLength();
645 }
646
647
648
649
650
651
652
653
654
655
656 public static Iterator<Tag> tagsIterator(final byte[] tags, final int offset, final int length) {
657 return new Iterator<Tag>() {
658 private int pos = offset;
659 private int endOffset = offset + length - 1;
660
661 @Override
662 public boolean hasNext() {
663 return this.pos < endOffset;
664 }
665
666 @Override
667 public Tag next() {
668 if (hasNext()) {
669 int curTagLen = Bytes.readAsInt(tags, this.pos, Tag.TAG_LENGTH_SIZE);
670 Tag tag = new Tag(tags, pos, curTagLen + Tag.TAG_LENGTH_SIZE);
671 this.pos += Bytes.SIZEOF_SHORT + curTagLen;
672 return tag;
673 }
674 return null;
675 }
676
677 @Override
678 public void remove() {
679 throw new UnsupportedOperationException();
680 }
681 };
682 }
683
684 public static byte[] cloneTags(Cell cell) {
685 byte[] output = new byte[cell.getTagsLength()];
686 copyTagsTo(cell, output, 0);
687 return output;
688 }
689
690
691
692
693
694
695
696
697 public static int copyTagsTo(Cell cell, byte[] destination, int destinationOffset) {
698 int tlen = cell.getTagsLength();
699 System.arraycopy(cell.getTagsArray(), cell.getTagsOffset(), destination,
700 destinationOffset, tlen);
701 return destinationOffset + tlen;
702 }
703
704
705
706
707
708 public static boolean overlappingKeys(final byte[] start1, final byte[] end1,
709 final byte[] start2, final byte[] end2) {
710 return (end2.length == 0 || start1.length == 0 || Bytes.compareTo(start1,
711 end2) < 0)
712 && (end1.length == 0 || start2.length == 0 || Bytes.compareTo(start2,
713 end1) < 0);
714 }
715
716
717
718
719
720
721
722
723
724 @InterfaceAudience.Private
725 public static void setSequenceId(Cell cell, long seqId) throws IOException {
726 if (cell instanceof SettableSequenceId) {
727 ((SettableSequenceId) cell).setSequenceId(seqId);
728 } else {
729 throw new IOException(new UnsupportedOperationException("Cell is not of type "
730 + SettableSequenceId.class.getName()));
731 }
732 }
733
734
735
736
737
738
739
740 public static void setTimestamp(Cell cell, long ts) throws IOException {
741 if (cell instanceof SettableTimestamp) {
742 ((SettableTimestamp) cell).setTimestamp(ts);
743 } else {
744 throw new IOException(new UnsupportedOperationException("Cell is not of type "
745 + SettableTimestamp.class.getName()));
746 }
747 }
748
749
750
751
752
753
754
755
756 public static void setTimestamp(Cell cell, byte[] ts, int tsOffset) throws IOException {
757 if (cell instanceof SettableTimestamp) {
758 ((SettableTimestamp) cell).setTimestamp(ts, tsOffset);
759 } else {
760 throw new IOException(new UnsupportedOperationException("Cell is not of type "
761 + SettableTimestamp.class.getName()));
762 }
763 }
764
765
766
767
768
769
770
771
772
773 public static boolean updateLatestStamp(Cell cell, long ts) throws IOException {
774 if (cell.getTimestamp() == HConstants.LATEST_TIMESTAMP) {
775 setTimestamp(cell, ts);
776 return true;
777 }
778 return false;
779 }
780
781
782
783
784
785
786
787
788
789
790 public static boolean updateLatestStamp(Cell cell, byte[] ts, int tsOffset) throws IOException {
791 if (cell.getTimestamp() == HConstants.LATEST_TIMESTAMP) {
792 setTimestamp(cell, ts, tsOffset);
793 return true;
794 }
795 return false;
796 }
797
798
799
800
801
802
803
804
805
806 public static void writeFlatKey(Cell cell, DataOutputStream out) throws IOException {
807 short rowLen = cell.getRowLength();
808 out.writeShort(rowLen);
809 out.write(cell.getRowArray(), cell.getRowOffset(), rowLen);
810 byte fLen = cell.getFamilyLength();
811 out.writeByte(fLen);
812 out.write(cell.getFamilyArray(), cell.getFamilyOffset(), fLen);
813 out.write(cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength());
814 out.writeLong(cell.getTimestamp());
815 out.writeByte(cell.getTypeByte());
816 }
817
818
819
820
821
822 public static String getCellKeyAsString(Cell cell) {
823 StringBuilder sb = new StringBuilder(Bytes.toStringBinary(
824 cell.getRowArray(), cell.getRowOffset(), cell.getRowLength()));
825 sb.append('/');
826 sb.append(cell.getFamilyLength() == 0? "":
827 Bytes.toStringBinary(cell.getFamilyArray(), cell.getFamilyOffset(), cell.getFamilyLength()));
828
829 if (cell.getFamilyLength() > 0) sb.append(':');
830 sb.append(cell.getQualifierLength() == 0? "":
831 Bytes.toStringBinary(cell.getQualifierArray(), cell.getQualifierOffset(),
832 cell.getQualifierLength()));
833 sb.append('/');
834 sb.append(KeyValue.humanReadableTimestamp(cell.getTimestamp()));
835 sb.append('/');
836 sb.append(Type.codeToType(cell.getTypeByte()));
837 sb.append("/vlen=");
838 sb.append(cell.getValueLength());
839 sb.append("/seqid=");
840 sb.append(cell.getSequenceId());
841 return sb.toString();
842 }
843
844
845
846
847
848
849
850
851
852 public static byte [] getCellKeySerializedAsKeyValueKey(final Cell cell) {
853 if (cell == null) return null;
854 byte [] b = new byte[KeyValueUtil.keyLength(cell)];
855 KeyValueUtil.appendKeyTo(cell, b, 0);
856 return b;
857 }
858
859
860
861
862
863
864
865
866
867 public static void writeRowKeyExcludingCommon(Cell cell, short rLen, int commonPrefix,
868 DataOutputStream out) throws IOException {
869 if (commonPrefix == 0) {
870 out.writeShort(rLen);
871 } else if (commonPrefix == 1) {
872 out.writeByte((byte) rLen);
873 commonPrefix--;
874 } else {
875 commonPrefix -= KeyValue.ROW_LENGTH_SIZE;
876 }
877 if (rLen > commonPrefix) {
878 out.write(cell.getRowArray(), cell.getRowOffset() + commonPrefix, rLen - commonPrefix);
879 }
880 }
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897 public static int findCommonPrefixInFlatKey(Cell c1, Cell c2, boolean bypassFamilyCheck,
898 boolean withTsType) {
899
900 short rLen1 = c1.getRowLength();
901 short rLen2 = c2.getRowLength();
902 int commonPrefix = KeyValue.ROW_LENGTH_SIZE;
903 if (rLen1 != rLen2) {
904
905 return ByteBufferUtils.findCommonPrefix(Bytes.toBytes(rLen1), 0, KeyValue.ROW_LENGTH_SIZE,
906 Bytes.toBytes(rLen2), 0, KeyValue.ROW_LENGTH_SIZE);
907 }
908
909 int rkCommonPrefix = ByteBufferUtils.findCommonPrefix(c1.getRowArray(), c1.getRowOffset(),
910 rLen1, c2.getRowArray(), c2.getRowOffset(), rLen2);
911 commonPrefix += rkCommonPrefix;
912 if (rkCommonPrefix != rLen1) {
913
914 return commonPrefix;
915 }
916
917 byte fLen1 = c1.getFamilyLength();
918 if (bypassFamilyCheck) {
919
920
921 commonPrefix += KeyValue.FAMILY_LENGTH_SIZE + fLen1;
922 } else {
923 byte fLen2 = c2.getFamilyLength();
924 if (fLen1 != fLen2) {
925
926 return commonPrefix;
927 }
928
929 commonPrefix += KeyValue.FAMILY_LENGTH_SIZE;
930
931 int fCommonPrefix = ByteBufferUtils.findCommonPrefix(c1.getFamilyArray(),
932 c1.getFamilyOffset(), fLen1, c2.getFamilyArray(), c2.getFamilyOffset(), fLen2);
933 commonPrefix += fCommonPrefix;
934 if (fCommonPrefix != fLen1) {
935 return commonPrefix;
936 }
937 }
938
939 int qLen1 = c1.getQualifierLength();
940 int qLen2 = c2.getQualifierLength();
941 int qCommon = ByteBufferUtils.findCommonPrefix(c1.getQualifierArray(), c1.getQualifierOffset(),
942 qLen1, c2.getQualifierArray(), c2.getQualifierOffset(), qLen2);
943 commonPrefix += qCommon;
944 if (!withTsType || Math.max(qLen1, qLen2) != qCommon) {
945 return commonPrefix;
946 }
947
948 int tsCommonPrefix = ByteBufferUtils.findCommonPrefix(Bytes.toBytes(c1.getTimestamp()), 0,
949 KeyValue.TIMESTAMP_SIZE, Bytes.toBytes(c2.getTimestamp()), 0, KeyValue.TIMESTAMP_SIZE);
950 commonPrefix += tsCommonPrefix;
951 if (tsCommonPrefix != KeyValue.TIMESTAMP_SIZE) {
952 return commonPrefix;
953 }
954
955 if (c1.getTypeByte() == c2.getTypeByte()) {
956 commonPrefix += KeyValue.TYPE_SIZE;
957 }
958 return commonPrefix;
959 }
960
961
962 public static String toString(Cell cell, boolean verbose) {
963 if (cell == null) {
964 return "";
965 }
966 StringBuilder builder = new StringBuilder();
967 String keyStr = getCellKeyAsString(cell);
968
969 String tag = null;
970 String value = null;
971 if (verbose) {
972
973 tag = Bytes.toStringBinary(cell.getTagsArray(), cell.getTagsOffset(), cell.getTagsLength());
974 value = Bytes.toStringBinary(cell.getValueArray(), cell.getValueOffset(),
975 cell.getValueLength());
976 }
977
978 builder
979 .append(keyStr);
980 if (tag != null && !tag.isEmpty()) {
981 builder.append("/").append(tag);
982 }
983 if (value != null) {
984 builder.append("/").append(value);
985 }
986
987 return builder.toString();
988 }
989
990
991
992 public static boolean equals(Cell a, Cell b) {
993 return matchingRow(a, b) && matchingFamily(a, b) && matchingQualifier(a, b)
994 && matchingTimestamp(a, b) && matchingType(a, b);
995 }
996
997 public static boolean matchingType(Cell a, Cell b) {
998 return a.getTypeByte() == b.getTypeByte();
999 }
1000 }