1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.hadoop.hbase;
21
22 import static org.apache.hadoop.hbase.util.Bytes.len;
23
24 import java.io.DataInput;
25 import java.io.DataOutput;
26 import java.io.EOFException;
27 import java.io.IOException;
28 import java.io.InputStream;
29 import java.io.OutputStream;
30 import java.nio.ByteBuffer;
31 import java.util.ArrayList;
32 import java.util.Arrays;
33 import java.util.Comparator;
34 import java.util.HashMap;
35 import java.util.List;
36 import java.util.Map;
37
38 import org.apache.commons.logging.Log;
39 import org.apache.commons.logging.LogFactory;
40 import org.apache.hadoop.hbase.classification.InterfaceAudience;
41 import org.apache.hadoop.hbase.io.HeapSize;
42 import org.apache.hadoop.hbase.io.util.StreamUtils;
43 import org.apache.hadoop.hbase.util.Bytes;
44 import org.apache.hadoop.hbase.util.ClassSize;
45 import org.apache.hadoop.io.IOUtils;
46 import org.apache.hadoop.io.RawComparator;
47
48 import com.google.common.annotations.VisibleForTesting;
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82 @InterfaceAudience.Private
83 public class KeyValue implements Cell, HeapSize, Cloneable, SettableSequenceId, SettableTimestamp {
84 private static final ArrayList<Tag> EMPTY_ARRAY_LIST = new ArrayList<Tag>();
85
86 static final Log LOG = LogFactory.getLog(KeyValue.class);
87
88
89
90
91 public static final char COLUMN_FAMILY_DELIMITER = ':';
92
93 public static final byte[] COLUMN_FAMILY_DELIM_ARRAY =
94 new byte[]{COLUMN_FAMILY_DELIMITER};
95
96
97
98
99
100 public static final KVComparator COMPARATOR = new KVComparator();
101
102
103
104
105 public static final KVComparator META_COMPARATOR = new MetaComparator();
106
107
108
109
110 public static final KVComparator RAW_COMPARATOR = new RawBytesComparator();
111
112
113 public static final int KEY_LENGTH_SIZE = Bytes.SIZEOF_INT;
114
115
116 public static final int TYPE_SIZE = Bytes.SIZEOF_BYTE;
117
118
119 public static final int ROW_LENGTH_SIZE = Bytes.SIZEOF_SHORT;
120
121
122 public static final int FAMILY_LENGTH_SIZE = Bytes.SIZEOF_BYTE;
123
124
125 public static final int TIMESTAMP_SIZE = Bytes.SIZEOF_LONG;
126
127
128 public static final int TIMESTAMP_TYPE_SIZE = TIMESTAMP_SIZE + TYPE_SIZE;
129
130
131 public static final int KEY_INFRASTRUCTURE_SIZE = ROW_LENGTH_SIZE
132 + FAMILY_LENGTH_SIZE + TIMESTAMP_TYPE_SIZE;
133
134
135
136 public static final int ROW_OFFSET =
137 Bytes.SIZEOF_INT
138 Bytes.SIZEOF_INT
139
140
141 public static final int KEYVALUE_INFRASTRUCTURE_SIZE = ROW_OFFSET;
142
143
144 public static final int TAGS_LENGTH_SIZE = Bytes.SIZEOF_SHORT;
145
146 public static final int KEYVALUE_WITH_TAGS_INFRASTRUCTURE_SIZE = ROW_OFFSET + TAGS_LENGTH_SIZE;
147
148 private static final int MAX_TAGS_LENGTH = (2 * Short.MAX_VALUE) + 1;
149
150
151
152
153
154
155
156
157
158
159
160
161 public static long getKeyValueDataStructureSize(int rlength,
162 int flength, int qlength, int vlength) {
163 return KeyValue.KEYVALUE_INFRASTRUCTURE_SIZE
164 + getKeyDataStructureSize(rlength, flength, qlength) + vlength;
165 }
166
167
168
169
170
171
172
173
174
175
176
177
178
179 public static long getKeyValueDataStructureSize(int rlength, int flength, int qlength,
180 int vlength, int tagsLength) {
181 if (tagsLength == 0) {
182 return getKeyValueDataStructureSize(rlength, flength, qlength, vlength);
183 }
184 return KeyValue.KEYVALUE_WITH_TAGS_INFRASTRUCTURE_SIZE
185 + getKeyDataStructureSize(rlength, flength, qlength) + vlength + tagsLength;
186 }
187
188
189
190
191
192
193
194
195
196
197
198 public static long getKeyValueDataStructureSize(int klength, int vlength, int tagsLength) {
199 if (tagsLength == 0) {
200 return KeyValue.KEYVALUE_INFRASTRUCTURE_SIZE + klength + vlength;
201 }
202 return KeyValue.KEYVALUE_WITH_TAGS_INFRASTRUCTURE_SIZE + klength + vlength + tagsLength;
203 }
204
205
206
207
208
209
210
211
212
213
214
215 public static long getKeyDataStructureSize(int rlength, int flength, int qlength) {
216 return KeyValue.KEY_INFRASTRUCTURE_SIZE + rlength + flength + qlength;
217 }
218
219
220
221
222
223
224 public static enum Type {
225 Minimum((byte)0),
226 Put((byte)4),
227
228 Delete((byte)8),
229 DeleteFamilyVersion((byte)10),
230 DeleteColumn((byte)12),
231 DeleteFamily((byte)14),
232
233
234 Maximum((byte)255);
235
236 private final byte code;
237
238 Type(final byte c) {
239 this.code = c;
240 }
241
242 public byte getCode() {
243 return this.code;
244 }
245
246
247
248
249
250
251
252 public static Type codeToType(final byte b) {
253 for (Type t : Type.values()) {
254 if (t.getCode() == b) {
255 return t;
256 }
257 }
258 throw new RuntimeException("Unknown code " + b);
259 }
260 }
261
262
263
264
265
266
267 public static final KeyValue LOWESTKEY =
268 new KeyValue(HConstants.EMPTY_BYTE_ARRAY, HConstants.LATEST_TIMESTAMP);
269
270
271
272 protected byte [] bytes = null;
273 protected int offset = 0;
274 protected int length = 0;
275
276
277
278
279
280
281 public static boolean isDelete(byte t) {
282 return Type.Delete.getCode() <= t && t <= Type.DeleteFamily.getCode();
283 }
284
285
286
287
288 @Override
289 public long getMvccVersion() {
290 return this.getSequenceId();
291 }
292
293
294
295
296 @Override
297 public long getSequenceId() {
298 return seqId;
299 }
300
301 @Override
302 public void setSequenceId(long seqId) {
303 this.seqId = seqId;
304 }
305
306
307 private long seqId = 0;
308
309
310
311
312
313 public KeyValue() {}
314
315
316
317
318
319
320 public KeyValue(final byte [] bytes) {
321 this(bytes, 0);
322 }
323
324
325
326
327
328
329
330
331 public KeyValue(final byte [] bytes, final int offset) {
332 this(bytes, offset, getLength(bytes, offset));
333 }
334
335
336
337
338
339
340
341
342 public KeyValue(final byte [] bytes, final int offset, final int length) {
343 this.bytes = bytes;
344 this.offset = offset;
345 this.length = length;
346 }
347
348
349
350
351
352
353
354
355
356
357 public KeyValue(final byte[] bytes, final int offset, final int length, long ts) {
358 this(bytes, offset, length, null, 0, 0, null, 0, 0, ts, Type.Maximum, null, 0, 0, null);
359 }
360
361
362
363
364
365
366
367
368
369 public KeyValue(final byte [] row, final long timestamp) {
370 this(row, null, null, timestamp, Type.Maximum, null);
371 }
372
373
374
375
376
377
378 public KeyValue(final byte [] row, final long timestamp, Type type) {
379 this(row, null, null, timestamp, type, null);
380 }
381
382
383
384
385
386
387
388
389 public KeyValue(final byte [] row, final byte [] family,
390 final byte [] qualifier) {
391 this(row, family, qualifier, HConstants.LATEST_TIMESTAMP, Type.Maximum);
392 }
393
394
395
396
397
398
399
400 public KeyValue(final byte [] row, final byte [] family,
401 final byte [] qualifier, final byte [] value) {
402 this(row, family, qualifier, HConstants.LATEST_TIMESTAMP, Type.Put, value);
403 }
404
405
406
407
408
409
410
411
412
413
414 public KeyValue(final byte[] row, final byte[] family,
415 final byte[] qualifier, final long timestamp, Type type) {
416 this(row, family, qualifier, timestamp, type, null);
417 }
418
419
420
421
422
423
424
425
426
427
428 public KeyValue(final byte[] row, final byte[] family,
429 final byte[] qualifier, final long timestamp, final byte[] value) {
430 this(row, family, qualifier, timestamp, Type.Put, value);
431 }
432
433
434
435
436
437
438
439
440
441
442
443 public KeyValue(final byte[] row, final byte[] family,
444 final byte[] qualifier, final long timestamp, final byte[] value,
445 final Tag[] tags) {
446 this(row, family, qualifier, timestamp, value, tags != null ? Arrays.asList(tags) : null);
447 }
448
449
450
451
452
453
454
455
456
457
458
459 public KeyValue(final byte[] row, final byte[] family,
460 final byte[] qualifier, final long timestamp, final byte[] value,
461 final List<Tag> tags) {
462 this(row, 0, row==null ? 0 : row.length,
463 family, 0, family==null ? 0 : family.length,
464 qualifier, 0, qualifier==null ? 0 : qualifier.length,
465 timestamp, Type.Put,
466 value, 0, value==null ? 0 : value.length, tags);
467 }
468
469
470
471
472
473
474
475
476
477
478
479 public KeyValue(final byte[] row, final byte[] family,
480 final byte[] qualifier, final long timestamp, Type type,
481 final byte[] value) {
482 this(row, 0, len(row), family, 0, len(family), qualifier, 0, len(qualifier),
483 timestamp, type, value, 0, len(value));
484 }
485
486
487
488
489
490
491
492
493
494
495
496
497
498 public KeyValue(final byte[] row, final byte[] family,
499 final byte[] qualifier, final long timestamp, Type type,
500 final byte[] value, final List<Tag> tags) {
501 this(row, family, qualifier, 0, qualifier==null ? 0 : qualifier.length,
502 timestamp, type, value, 0, value==null ? 0 : value.length, tags);
503 }
504
505
506
507
508
509
510
511
512
513
514
515 public KeyValue(final byte[] row, final byte[] family,
516 final byte[] qualifier, final long timestamp, Type type,
517 final byte[] value, final byte[] tags) {
518 this(row, family, qualifier, 0, qualifier==null ? 0 : qualifier.length,
519 timestamp, type, value, 0, value==null ? 0 : value.length, tags);
520 }
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536 public KeyValue(byte [] row, byte [] family,
537 byte [] qualifier, int qoffset, int qlength, long timestamp, Type type,
538 byte [] value, int voffset, int vlength, List<Tag> tags) {
539 this(row, 0, row==null ? 0 : row.length,
540 family, 0, family==null ? 0 : family.length,
541 qualifier, qoffset, qlength, timestamp, type,
542 value, voffset, vlength, tags);
543 }
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558 public KeyValue(byte [] row, byte [] family,
559 byte [] qualifier, int qoffset, int qlength, long timestamp, Type type,
560 byte [] value, int voffset, int vlength, byte[] tags) {
561 this(row, 0, row==null ? 0 : row.length,
562 family, 0, family==null ? 0 : family.length,
563 qualifier, qoffset, qlength, timestamp, type,
564 value, voffset, vlength, tags, 0, tags==null ? 0 : tags.length);
565 }
566
567
568
569
570
571
572
573
574 public KeyValue(final byte [] row, final int roffset, final int rlength,
575 final byte [] family, final int foffset, final int flength,
576 final byte [] qualifier, final int qoffset, final int qlength,
577 final long timestamp, final Type type,
578 final byte [] value, final int voffset, final int vlength) {
579 this(row, roffset, rlength, family, foffset, flength, qualifier, qoffset,
580 qlength, timestamp, type, value, voffset, vlength, null);
581 }
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609 public KeyValue(byte [] buffer, final int boffset,
610 final byte [] row, final int roffset, final int rlength,
611 final byte [] family, final int foffset, final int flength,
612 final byte [] qualifier, final int qoffset, final int qlength,
613 final long timestamp, final Type type,
614 final byte [] value, final int voffset, final int vlength,
615 final Tag[] tags) {
616 this.bytes = buffer;
617 this.length = writeByteArray(buffer, boffset,
618 row, roffset, rlength,
619 family, foffset, flength, qualifier, qoffset, qlength,
620 timestamp, type, value, voffset, vlength, tags);
621 this.offset = boffset;
622 }
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645 public KeyValue(final byte [] row, final int roffset, final int rlength,
646 final byte [] family, final int foffset, final int flength,
647 final byte [] qualifier, final int qoffset, final int qlength,
648 final long timestamp, final Type type,
649 final byte [] value, final int voffset, final int vlength,
650 final List<Tag> tags) {
651 this.bytes = createByteArray(row, roffset, rlength,
652 family, foffset, flength, qualifier, qoffset, qlength,
653 timestamp, type, value, voffset, vlength, tags);
654 this.length = bytes.length;
655 this.offset = 0;
656 }
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675 public KeyValue(final byte [] row, final int roffset, final int rlength,
676 final byte [] family, final int foffset, final int flength,
677 final byte [] qualifier, final int qoffset, final int qlength,
678 final long timestamp, final Type type,
679 final byte [] value, final int voffset, final int vlength,
680 final byte[] tags, final int tagsOffset, final int tagsLength) {
681 this.bytes = createByteArray(row, roffset, rlength,
682 family, foffset, flength, qualifier, qoffset, qlength,
683 timestamp, type, value, voffset, vlength, tags, tagsOffset, tagsLength);
684 this.length = bytes.length;
685 this.offset = 0;
686 }
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701 public KeyValue(final int rlength,
702 final int flength,
703 final int qlength,
704 final long timestamp, final Type type,
705 final int vlength) {
706 this(rlength, flength, qlength, timestamp, type, vlength, 0);
707 }
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723 public KeyValue(final int rlength,
724 final int flength,
725 final int qlength,
726 final long timestamp, final Type type,
727 final int vlength, final int tagsLength) {
728 this.bytes = createEmptyByteArray(rlength, flength, qlength, timestamp, type, vlength,
729 tagsLength);
730 this.length = bytes.length;
731 this.offset = 0;
732 }
733
734
735 public KeyValue(byte[] row, int roffset, int rlength,
736 byte[] family, int foffset, int flength,
737 ByteBuffer qualifier, long ts, Type type, ByteBuffer value, List<Tag> tags) {
738 this.bytes = createByteArray(row, roffset, rlength, family, foffset, flength,
739 qualifier, 0, qualifier == null ? 0 : qualifier.remaining(), ts, type,
740 value, 0, value == null ? 0 : value.remaining(), tags);
741 this.length = bytes.length;
742 this.offset = 0;
743 }
744
745 public KeyValue(Cell c) {
746 this(c.getRowArray(), c.getRowOffset(), (int)c.getRowLength(),
747 c.getFamilyArray(), c.getFamilyOffset(), (int)c.getFamilyLength(),
748 c.getQualifierArray(), c.getQualifierOffset(), (int) c.getQualifierLength(),
749 c.getTimestamp(), Type.codeToType(c.getTypeByte()), c.getValueArray(), c.getValueOffset(),
750 c.getValueLength(), c.getTagsArray(), c.getTagsOffset(), c.getTagsLength());
751 this.seqId = c.getSequenceId();
752 }
753
754
755
756
757
758
759
760
761
762
763 @Deprecated
764 public static KeyValue createFirstOnRow(final byte [] row) {
765 return KeyValueUtil.createFirstOnRow(row, HConstants.LATEST_TIMESTAMP);
766 }
767
768
769
770
771
772
773
774
775
776
777
778
779 @Deprecated
780 public static KeyValue createFirstOnRow(final byte [] row, final byte [] family,
781 final byte [] qualifier) {
782 return KeyValueUtil.createFirstOnRow(row, family, qualifier);
783 }
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803 @Deprecated
804 public static KeyValue createFirstOnRow(final byte [] row,
805 final int roffset, final int rlength, final byte [] family,
806 final int foffset, final int flength, final byte [] qualifier,
807 final int qoffset, final int qlength) {
808 return new KeyValue(row, roffset, rlength, family,
809 foffset, flength, qualifier, qoffset, qlength,
810 HConstants.LATEST_TIMESTAMP, Type.Maximum, null, 0, 0);
811 }
812
813
814
815
816
817
818
819
820
821
822
823
824 private static byte[] createEmptyByteArray(final int rlength, int flength,
825 int qlength, final long timestamp, final Type type, int vlength, int tagsLength) {
826 if (rlength > Short.MAX_VALUE) {
827 throw new IllegalArgumentException("Row > " + Short.MAX_VALUE);
828 }
829 if (flength > Byte.MAX_VALUE) {
830 throw new IllegalArgumentException("Family > " + Byte.MAX_VALUE);
831 }
832
833 if (qlength > Integer.MAX_VALUE - rlength - flength) {
834 throw new IllegalArgumentException("Qualifier > " + Integer.MAX_VALUE);
835 }
836 checkForTagsLength(tagsLength);
837
838 long longkeylength = getKeyDataStructureSize(rlength, flength, qlength);
839 if (longkeylength > Integer.MAX_VALUE) {
840 throw new IllegalArgumentException("keylength " + longkeylength + " > " +
841 Integer.MAX_VALUE);
842 }
843 int keylength = (int)longkeylength;
844
845 if (vlength > HConstants.MAXIMUM_VALUE_LENGTH) {
846 throw new IllegalArgumentException("Valuer > " +
847 HConstants.MAXIMUM_VALUE_LENGTH);
848 }
849
850
851 byte[] bytes= new byte[(int) getKeyValueDataStructureSize(rlength, flength, qlength, vlength,
852 tagsLength)];
853
854 int pos = 0;
855 pos = Bytes.putInt(bytes, pos, keylength);
856 pos = Bytes.putInt(bytes, pos, vlength);
857 pos = Bytes.putShort(bytes, pos, (short)(rlength & 0x0000ffff));
858 pos += rlength;
859 pos = Bytes.putByte(bytes, pos, (byte)(flength & 0x0000ff));
860 pos += flength + qlength;
861 pos = Bytes.putLong(bytes, pos, timestamp);
862 pos = Bytes.putByte(bytes, pos, type.getCode());
863 pos += vlength;
864 if (tagsLength > 0) {
865 pos = Bytes.putAsShort(bytes, pos, tagsLength);
866 }
867 return bytes;
868 }
869
870
871
872
873
874
875
876
877
878
879
880
881
882 private static void checkParameters(final byte [] row, final int rlength,
883 final byte [] family, int flength, int qlength, int vlength)
884 throws IllegalArgumentException {
885 if (rlength > Short.MAX_VALUE) {
886 throw new IllegalArgumentException("Row > " + Short.MAX_VALUE);
887 }
888 if (row == null) {
889 throw new IllegalArgumentException("Row is null");
890 }
891
892 flength = family == null ? 0 : flength;
893 if (flength > Byte.MAX_VALUE) {
894 throw new IllegalArgumentException("Family > " + Byte.MAX_VALUE);
895 }
896
897 if (qlength > Integer.MAX_VALUE - rlength - flength) {
898 throw new IllegalArgumentException("Qualifier > " + Integer.MAX_VALUE);
899 }
900
901 long longKeyLength = getKeyDataStructureSize(rlength, flength, qlength);
902 if (longKeyLength > Integer.MAX_VALUE) {
903 throw new IllegalArgumentException("keylength " + longKeyLength + " > " +
904 Integer.MAX_VALUE);
905 }
906
907 if (vlength > HConstants.MAXIMUM_VALUE_LENGTH) {
908 throw new IllegalArgumentException("Value length " + vlength + " > " +
909 HConstants.MAXIMUM_VALUE_LENGTH);
910 }
911 }
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938 public static int writeByteArray(byte [] buffer, final int boffset,
939 final byte [] row, final int roffset, final int rlength,
940 final byte [] family, final int foffset, int flength,
941 final byte [] qualifier, final int qoffset, int qlength,
942 final long timestamp, final Type type,
943 final byte [] value, final int voffset, int vlength, Tag[] tags) {
944
945 checkParameters(row, rlength, family, flength, qlength, vlength);
946
947
948 int tagsLength = 0;
949 if (tags != null && tags.length > 0) {
950 for (Tag t: tags) {
951 tagsLength += t.getLength();
952 }
953 }
954 checkForTagsLength(tagsLength);
955 int keyLength = (int) getKeyDataStructureSize(rlength, flength, qlength);
956 int keyValueLength = (int) getKeyValueDataStructureSize(rlength, flength, qlength, vlength,
957 tagsLength);
958 if (keyValueLength > buffer.length - boffset) {
959 throw new IllegalArgumentException("Buffer size " + (buffer.length - boffset) + " < " +
960 keyValueLength);
961 }
962
963
964 int pos = boffset;
965 pos = Bytes.putInt(buffer, pos, keyLength);
966 pos = Bytes.putInt(buffer, pos, vlength);
967 pos = Bytes.putShort(buffer, pos, (short)(rlength & 0x0000ffff));
968 pos = Bytes.putBytes(buffer, pos, row, roffset, rlength);
969 pos = Bytes.putByte(buffer, pos, (byte) (flength & 0x0000ff));
970 if (flength != 0) {
971 pos = Bytes.putBytes(buffer, pos, family, foffset, flength);
972 }
973 if (qlength != 0) {
974 pos = Bytes.putBytes(buffer, pos, qualifier, qoffset, qlength);
975 }
976 pos = Bytes.putLong(buffer, pos, timestamp);
977 pos = Bytes.putByte(buffer, pos, type.getCode());
978 if (value != null && value.length > 0) {
979 pos = Bytes.putBytes(buffer, pos, value, voffset, vlength);
980 }
981
982 if (tagsLength > 0) {
983 pos = Bytes.putAsShort(buffer, pos, tagsLength);
984 for (Tag t : tags) {
985 pos = Bytes.putBytes(buffer, pos, t.getBuffer(), t.getOffset(), t.getLength());
986 }
987 }
988 return keyValueLength;
989 }
990
991 private static void checkForTagsLength(int tagsLength) {
992 if (tagsLength > MAX_TAGS_LENGTH) {
993 throw new IllegalArgumentException("tagslength "+ tagsLength + " > " + MAX_TAGS_LENGTH);
994 }
995 }
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015 private static byte [] createByteArray(final byte [] row, final int roffset,
1016 final int rlength, final byte [] family, final int foffset, int flength,
1017 final byte [] qualifier, final int qoffset, int qlength,
1018 final long timestamp, final Type type,
1019 final byte [] value, final int voffset,
1020 int vlength, byte[] tags, int tagsOffset, int tagsLength) {
1021
1022 checkParameters(row, rlength, family, flength, qlength, vlength);
1023 checkForTagsLength(tagsLength);
1024
1025 int keyLength = (int) getKeyDataStructureSize(rlength, flength, qlength);
1026 byte[] bytes = new byte[(int) getKeyValueDataStructureSize(rlength, flength, qlength, vlength,
1027 tagsLength)];
1028
1029 int pos = 0;
1030 pos = Bytes.putInt(bytes, pos, keyLength);
1031 pos = Bytes.putInt(bytes, pos, vlength);
1032 pos = Bytes.putShort(bytes, pos, (short)(rlength & 0x0000ffff));
1033 pos = Bytes.putBytes(bytes, pos, row, roffset, rlength);
1034 pos = Bytes.putByte(bytes, pos, (byte)(flength & 0x0000ff));
1035 if(flength != 0) {
1036 pos = Bytes.putBytes(bytes, pos, family, foffset, flength);
1037 }
1038 if(qlength != 0) {
1039 pos = Bytes.putBytes(bytes, pos, qualifier, qoffset, qlength);
1040 }
1041 pos = Bytes.putLong(bytes, pos, timestamp);
1042 pos = Bytes.putByte(bytes, pos, type.getCode());
1043 if (value != null && value.length > 0) {
1044 pos = Bytes.putBytes(bytes, pos, value, voffset, vlength);
1045 }
1046
1047 if (tagsLength > 0) {
1048 pos = Bytes.putAsShort(bytes, pos, tagsLength);
1049 pos = Bytes.putBytes(bytes, pos, tags, tagsOffset, tagsLength);
1050 }
1051 return bytes;
1052 }
1053
1054
1055
1056
1057
1058 private static byte [] createByteArray(final byte [] row, final int roffset,
1059 final int rlength, final byte [] family, final int foffset, int flength,
1060 final Object qualifier, final int qoffset, int qlength,
1061 final long timestamp, final Type type,
1062 final Object value, final int voffset, int vlength, List<Tag> tags) {
1063
1064 checkParameters(row, rlength, family, flength, qlength, vlength);
1065
1066
1067 int tagsLength = 0;
1068 if (tags != null && !tags.isEmpty()) {
1069 for (Tag t : tags) {
1070 tagsLength += t.getLength();
1071 }
1072 }
1073 checkForTagsLength(tagsLength);
1074
1075 int keyLength = (int) getKeyDataStructureSize(rlength, flength, qlength);
1076 byte[] bytes = new byte[(int) getKeyValueDataStructureSize(rlength, flength, qlength, vlength,
1077 tagsLength)];
1078
1079
1080 int pos = 0;
1081 pos = Bytes.putInt(bytes, pos, keyLength);
1082
1083 pos = Bytes.putInt(bytes, pos, vlength);
1084 pos = Bytes.putShort(bytes, pos, (short)(rlength & 0x0000ffff));
1085 pos = Bytes.putBytes(bytes, pos, row, roffset, rlength);
1086 pos = Bytes.putByte(bytes, pos, (byte)(flength & 0x0000ff));
1087 if(flength != 0) {
1088 pos = Bytes.putBytes(bytes, pos, family, foffset, flength);
1089 }
1090 if (qlength > 0) {
1091 if (qualifier instanceof ByteBuffer) {
1092 pos = Bytes.putByteBuffer(bytes, pos, (ByteBuffer) qualifier);
1093 } else {
1094 pos = Bytes.putBytes(bytes, pos, (byte[]) qualifier, qoffset, qlength);
1095 }
1096 }
1097 pos = Bytes.putLong(bytes, pos, timestamp);
1098 pos = Bytes.putByte(bytes, pos, type.getCode());
1099 if (vlength > 0) {
1100 if (value instanceof ByteBuffer) {
1101 pos = Bytes.putByteBuffer(bytes, pos, (ByteBuffer) value);
1102 } else {
1103 pos = Bytes.putBytes(bytes, pos, (byte[]) value, voffset, vlength);
1104 }
1105 }
1106
1107 if (tagsLength > 0) {
1108 pos = Bytes.putAsShort(bytes, pos, tagsLength);
1109 for (Tag t : tags) {
1110 pos = Bytes.putBytes(bytes, pos, t.getBuffer(), t.getOffset(), t.getLength());
1111 }
1112 }
1113 return bytes;
1114 }
1115
1116
1117
1118
1119 @Override
1120 public boolean equals(Object other) {
1121 if (!(other instanceof Cell)) {
1122 return false;
1123 }
1124 return CellComparator.equals(this, (Cell)other);
1125 }
1126
1127
1128
1129
1130 @Override
1131 public int hashCode() {
1132 return CellComparator.hashCodeIgnoreMvcc(this);
1133 }
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146 @Override
1147 public KeyValue clone() throws CloneNotSupportedException {
1148 super.clone();
1149 byte [] b = new byte[this.length];
1150 System.arraycopy(this.bytes, this.offset, b, 0, this.length);
1151 KeyValue ret = new KeyValue(b, 0, b.length);
1152
1153
1154
1155 ret.setSequenceId(seqId);
1156 return ret;
1157 }
1158
1159
1160
1161
1162
1163
1164 public KeyValue shallowCopy() {
1165 KeyValue shallowCopy = new KeyValue(this.bytes, this.offset, this.length);
1166 shallowCopy.setSequenceId(this.seqId);
1167 return shallowCopy;
1168 }
1169
1170
1171
1172
1173
1174
1175
1176 @Override
1177 public String toString() {
1178 if (this.bytes == null || this.bytes.length == 0) {
1179 return "empty";
1180 }
1181 return keyToString(this.bytes, this.offset + ROW_OFFSET, getKeyLength()) + "/vlen="
1182 + getValueLength() + "/seqid=" + seqId;
1183 }
1184
1185
1186
1187
1188
1189 public static String keyToString(final byte [] k) {
1190 if (k == null) {
1191 return "";
1192 }
1193 return keyToString(k, 0, k.length);
1194 }
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204 public Map<String, Object> toStringMap() {
1205 Map<String, Object> stringMap = new HashMap<String, Object>();
1206 stringMap.put("row", Bytes.toStringBinary(getRow()));
1207 stringMap.put("family", Bytes.toStringBinary(getFamily()));
1208 stringMap.put("qualifier", Bytes.toStringBinary(getQualifier()));
1209 stringMap.put("timestamp", getTimestamp());
1210 stringMap.put("vlen", getValueLength());
1211 List<Tag> tags = getTags();
1212 if (tags != null) {
1213 List<String> tagsString = new ArrayList<String>();
1214 for (Tag t : tags) {
1215 tagsString.add((t.getType()) + ":" +Bytes.toStringBinary(t.getValue()));
1216 }
1217 stringMap.put("tag", tagsString);
1218 }
1219 return stringMap;
1220 }
1221
1222
1223
1224
1225
1226
1227
1228
1229 public static String keyToString(final byte [] b, final int o, final int l) {
1230 if (b == null) return "";
1231 int rowlength = Bytes.toShort(b, o);
1232 String row = Bytes.toStringBinary(b, o + Bytes.SIZEOF_SHORT, rowlength);
1233 int columnoffset = o + Bytes.SIZEOF_SHORT + 1 + rowlength;
1234 int familylength = b[columnoffset - 1];
1235 int columnlength = l - ((columnoffset - o) + TIMESTAMP_TYPE_SIZE);
1236 String family = familylength == 0? "":
1237 Bytes.toStringBinary(b, columnoffset, familylength);
1238 String qualifier = columnlength == 0? "":
1239 Bytes.toStringBinary(b, columnoffset + familylength,
1240 columnlength - familylength);
1241 long timestamp = Bytes.toLong(b, o + (l - TIMESTAMP_TYPE_SIZE));
1242 String timestampStr = humanReadableTimestamp(timestamp);
1243 byte type = b[o + l - 1];
1244 return row + "/" + family +
1245 (family != null && family.length() > 0? ":" :"") +
1246 qualifier + "/" + timestampStr + "/" + Type.codeToType(type);
1247 }
1248
1249 public static String humanReadableTimestamp(final long timestamp) {
1250 if (timestamp == HConstants.LATEST_TIMESTAMP) {
1251 return "LATEST_TIMESTAMP";
1252 }
1253 if (timestamp == HConstants.OLDEST_TIMESTAMP) {
1254 return "OLDEST_TIMESTAMP";
1255 }
1256 return String.valueOf(timestamp);
1257 }
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269 @Deprecated
1270 public byte [] getBuffer() {
1271 return this.bytes;
1272 }
1273
1274
1275
1276
1277 public int getOffset() {
1278 return this.offset;
1279 }
1280
1281
1282
1283
1284 public int getLength() {
1285 return length;
1286 }
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301 private static int getLength(byte [] bytes, int offset) {
1302 int klength = ROW_OFFSET + Bytes.toInt(bytes, offset);
1303 int vlength = Bytes.toInt(bytes, offset + Bytes.SIZEOF_INT);
1304 return klength + vlength;
1305 }
1306
1307
1308
1309
1310 public int getKeyOffset() {
1311 return this.offset + ROW_OFFSET;
1312 }
1313
1314 public String getKeyString() {
1315 return Bytes.toStringBinary(getBuffer(), getKeyOffset(), getKeyLength());
1316 }
1317
1318
1319
1320
1321 public int getKeyLength() {
1322 return Bytes.toInt(this.bytes, this.offset);
1323 }
1324
1325
1326
1327
1328 @Override
1329 public byte[] getValueArray() {
1330 return bytes;
1331 }
1332
1333
1334
1335
1336 @Override
1337 public int getValueOffset() {
1338 int voffset = getKeyOffset() + getKeyLength();
1339 return voffset;
1340 }
1341
1342
1343
1344
1345 @Override
1346 public int getValueLength() {
1347 int vlength = Bytes.toInt(this.bytes, this.offset + Bytes.SIZEOF_INT);
1348 return vlength;
1349 }
1350
1351
1352
1353
1354 @Override
1355 public byte[] getRowArray() {
1356 return bytes;
1357 }
1358
1359
1360
1361
1362 @Override
1363 public int getRowOffset() {
1364 return getKeyOffset() + Bytes.SIZEOF_SHORT;
1365 }
1366
1367
1368
1369
1370 @Override
1371 public short getRowLength() {
1372 return Bytes.toShort(this.bytes, getKeyOffset());
1373 }
1374
1375
1376
1377
1378 @Override
1379 public byte[] getFamilyArray() {
1380 return bytes;
1381 }
1382
1383
1384
1385
1386 @Override
1387 public int getFamilyOffset() {
1388 return getFamilyOffset(getRowLength());
1389 }
1390
1391
1392
1393
1394 private int getFamilyOffset(int rlength) {
1395 return this.offset + ROW_OFFSET + Bytes.SIZEOF_SHORT + rlength + Bytes.SIZEOF_BYTE;
1396 }
1397
1398
1399
1400
1401 @Override
1402 public byte getFamilyLength() {
1403 return getFamilyLength(getFamilyOffset());
1404 }
1405
1406
1407
1408
1409 public byte getFamilyLength(int foffset) {
1410 return this.bytes[foffset-1];
1411 }
1412
1413
1414
1415
1416 @Override
1417 public byte[] getQualifierArray() {
1418 return bytes;
1419 }
1420
1421
1422
1423
1424 @Override
1425 public int getQualifierOffset() {
1426 return getQualifierOffset(getFamilyOffset());
1427 }
1428
1429
1430
1431
1432 private int getQualifierOffset(int foffset) {
1433 return foffset + getFamilyLength(foffset);
1434 }
1435
1436
1437
1438
1439 @Override
1440 public int getQualifierLength() {
1441 return getQualifierLength(getRowLength(),getFamilyLength());
1442 }
1443
1444
1445
1446
1447 private int getQualifierLength(int rlength, int flength) {
1448 return getKeyLength() - (int) getKeyDataStructureSize(rlength, flength, 0);
1449 }
1450
1451
1452
1453
1454 public int getTimestampOffset() {
1455 return getTimestampOffset(getKeyLength());
1456 }
1457
1458
1459
1460
1461
1462 private int getTimestampOffset(final int keylength) {
1463 return getKeyOffset() + keylength - TIMESTAMP_TYPE_SIZE;
1464 }
1465
1466
1467
1468
1469 public boolean isLatestTimestamp() {
1470 return Bytes.equals(getBuffer(), getTimestampOffset(), Bytes.SIZEOF_LONG,
1471 HConstants.LATEST_TIMESTAMP_BYTES, 0, Bytes.SIZEOF_LONG);
1472 }
1473
1474
1475
1476
1477
1478
1479 public boolean updateLatestStamp(final byte [] now) {
1480 if (this.isLatestTimestamp()) {
1481 int tsOffset = getTimestampOffset();
1482 System.arraycopy(now, 0, this.bytes, tsOffset, Bytes.SIZEOF_LONG);
1483
1484 return true;
1485 }
1486 return false;
1487 }
1488
1489 @Override
1490 public void setTimestamp(long ts) {
1491 Bytes.putBytes(this.bytes, this.getTimestampOffset(), Bytes.toBytes(ts), 0, Bytes.SIZEOF_LONG);
1492 }
1493
1494 @Override
1495 public void setTimestamp(byte[] ts, int tsOffset) {
1496 Bytes.putBytes(this.bytes, this.getTimestampOffset(), ts, tsOffset, Bytes.SIZEOF_LONG);
1497 }
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512 public byte [] getKey() {
1513 int keylength = getKeyLength();
1514 byte [] key = new byte[keylength];
1515 System.arraycopy(getBuffer(), getKeyOffset(), key, 0, keylength);
1516 return key;
1517 }
1518
1519
1520
1521
1522
1523
1524
1525
1526 @Override
1527 @Deprecated
1528 public byte [] getValue() {
1529 return CellUtil.cloneValue(this);
1530 }
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540 @Override
1541 @Deprecated
1542 public byte [] getRow() {
1543 return CellUtil.cloneRow(this);
1544 }
1545
1546
1547
1548
1549
1550 @Override
1551 public long getTimestamp() {
1552 return getTimestamp(getKeyLength());
1553 }
1554
1555
1556
1557
1558
1559 long getTimestamp(final int keylength) {
1560 int tsOffset = getTimestampOffset(keylength);
1561 return Bytes.toLong(this.bytes, tsOffset);
1562 }
1563
1564
1565
1566
1567 @Deprecated
1568 public byte getType() {
1569 return getTypeByte();
1570 }
1571
1572
1573
1574
1575 @Override
1576 public byte getTypeByte() {
1577 return this.bytes[this.offset + getKeyLength() - 1 + ROW_OFFSET];
1578 }
1579
1580
1581
1582
1583
1584
1585 @Deprecated
1586 public boolean isDelete() {
1587 return KeyValue.isDelete(getType());
1588 }
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598 @Override
1599 @Deprecated
1600 public byte [] getFamily() {
1601 return CellUtil.cloneFamily(this);
1602 }
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613 @Override
1614 @Deprecated
1615 public byte [] getQualifier() {
1616 return CellUtil.cloneQualifier(this);
1617 }
1618
1619
1620
1621
1622 @Override
1623 public int getTagsOffset() {
1624 int tagsLen = getTagsLength();
1625 if (tagsLen == 0) {
1626 return this.offset + this.length;
1627 }
1628 return this.offset + this.length - tagsLen;
1629 }
1630
1631
1632
1633
1634 @Override
1635 public int getTagsLength() {
1636 int tagsLen = this.length - (getKeyLength() + getValueLength() + KEYVALUE_INFRASTRUCTURE_SIZE);
1637 if (tagsLen > 0) {
1638
1639
1640 tagsLen -= TAGS_LENGTH_SIZE;
1641 }
1642 return tagsLen;
1643 }
1644
1645
1646
1647
1648
1649 public List<Tag> getTags() {
1650 int tagsLength = getTagsLength();
1651 if (tagsLength == 0) {
1652 return EMPTY_ARRAY_LIST;
1653 }
1654 return Tag.asList(getTagsArray(), getTagsOffset(), tagsLength);
1655 }
1656
1657
1658
1659
1660 @Override
1661 public byte[] getTagsArray() {
1662 return bytes;
1663 }
1664
1665
1666
1667
1668
1669
1670
1671
1672 public KeyValue createKeyOnly(boolean lenAsVal) {
1673
1674
1675 int dataLen = lenAsVal? Bytes.SIZEOF_INT : 0;
1676 byte [] newBuffer = new byte[getKeyLength() + ROW_OFFSET + dataLen];
1677 System.arraycopy(this.bytes, this.offset, newBuffer, 0,
1678 Math.min(newBuffer.length,this.length));
1679 Bytes.putInt(newBuffer, Bytes.SIZEOF_INT, dataLen);
1680 if (lenAsVal) {
1681 Bytes.putInt(newBuffer, newBuffer.length - dataLen, this.getValueLength());
1682 }
1683 return new KeyValue(newBuffer);
1684 }
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699 public static byte [][] parseColumn(byte [] c) {
1700 final int index = getDelimiter(c, 0, c.length, COLUMN_FAMILY_DELIMITER);
1701 if (index == -1) {
1702
1703 return new byte [][] { c };
1704 } else if(index == c.length - 1) {
1705
1706 byte [] family = new byte[c.length-1];
1707 System.arraycopy(c, 0, family, 0, family.length);
1708 return new byte [][] { family, HConstants.EMPTY_BYTE_ARRAY};
1709 }
1710
1711 final byte [][] result = new byte [2][];
1712 result[0] = new byte [index];
1713 System.arraycopy(c, 0, result[0], 0, index);
1714 final int len = c.length - (index + 1);
1715 result[1] = new byte[len];
1716 System.arraycopy(c, index + 1
1717 return result;
1718 }
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728 public static byte [] makeColumn(byte [] family, byte [] qualifier) {
1729 return Bytes.add(family, COLUMN_FAMILY_DELIM_ARRAY, qualifier);
1730 }
1731
1732
1733
1734
1735
1736
1737
1738 public static int getDelimiter(final byte [] b, int offset, final int length,
1739 final int delimiter) {
1740 if (b == null) {
1741 throw new IllegalArgumentException("Passed buffer is null");
1742 }
1743 int result = -1;
1744 for (int i = offset; i < length + offset; i++) {
1745 if (b[i] == delimiter) {
1746 result = i;
1747 break;
1748 }
1749 }
1750 return result;
1751 }
1752
1753
1754
1755
1756
1757
1758
1759 public static int getDelimiterInReverse(final byte [] b, final int offset,
1760 final int length, final int delimiter) {
1761 if (b == null) {
1762 throw new IllegalArgumentException("Passed buffer is null");
1763 }
1764 int result = -1;
1765 for (int i = (offset + length) - 1; i >= offset; i--) {
1766 if (b[i] == delimiter) {
1767 result = i;
1768 break;
1769 }
1770 }
1771 return result;
1772 }
1773
1774
1775
1776
1777
1778 public static class MetaComparator extends KVComparator {
1779
1780
1781
1782
1783 @Override
1784 public int compare(final Cell left, final Cell right) {
1785 int c = compareRowKey(left, right);
1786 if (c != 0) {
1787 return c;
1788 }
1789 return CellComparator.compareWithoutRow(left, right);
1790 }
1791
1792 @Override
1793 public int compareOnlyKeyPortion(Cell left, Cell right) {
1794 return compare(left, right);
1795 }
1796
1797 @Override
1798 public int compareRows(byte [] left, int loffset, int llength,
1799 byte [] right, int roffset, int rlength) {
1800 int leftDelimiter = getDelimiter(left, loffset, llength,
1801 HConstants.DELIMITER);
1802 int rightDelimiter = getDelimiter(right, roffset, rlength,
1803 HConstants.DELIMITER);
1804
1805 int lpart = (leftDelimiter < 0 ? llength :leftDelimiter - loffset);
1806 int rpart = (rightDelimiter < 0 ? rlength :rightDelimiter - roffset);
1807 int result = Bytes.compareTo(left, loffset, lpart, right, roffset, rpart);
1808 if (result != 0) {
1809 return result;
1810 } else {
1811 if (leftDelimiter < 0 && rightDelimiter >= 0) {
1812 return -1;
1813 } else if (rightDelimiter < 0 && leftDelimiter >= 0) {
1814 return 1;
1815 } else if (leftDelimiter < 0 && rightDelimiter < 0) {
1816 return 0;
1817 }
1818 }
1819
1820
1821 leftDelimiter++;
1822 rightDelimiter++;
1823 int leftFarDelimiter = getDelimiterInReverse(left, leftDelimiter,
1824 llength - (leftDelimiter - loffset), HConstants.DELIMITER);
1825 int rightFarDelimiter = getDelimiterInReverse(right,
1826 rightDelimiter, rlength - (rightDelimiter - roffset),
1827 HConstants.DELIMITER);
1828
1829 lpart = (leftFarDelimiter < 0 ? llength + loffset: leftFarDelimiter) - leftDelimiter;
1830 rpart = (rightFarDelimiter < 0 ? rlength + roffset: rightFarDelimiter)- rightDelimiter;
1831 result = super.compareRows(left, leftDelimiter, lpart, right, rightDelimiter, rpart);
1832 if (result != 0) {
1833 return result;
1834 } else {
1835 if (leftDelimiter < 0 && rightDelimiter >= 0) {
1836 return -1;
1837 } else if (rightDelimiter < 0 && leftDelimiter >= 0) {
1838 return 1;
1839 } else if (leftDelimiter < 0 && rightDelimiter < 0) {
1840 return 0;
1841 }
1842 }
1843
1844 leftFarDelimiter++;
1845 rightFarDelimiter++;
1846 result = Bytes.compareTo(left, leftFarDelimiter, llength - (leftFarDelimiter - loffset),
1847 right, rightFarDelimiter, rlength - (rightFarDelimiter - roffset));
1848 return result;
1849 }
1850
1851
1852
1853
1854 @Override
1855 public byte[] getShortMidpointKey(final byte[] leftKey, final byte[] rightKey) {
1856 return Arrays.copyOf(rightKey, rightKey.length);
1857 }
1858
1859
1860
1861
1862
1863
1864
1865 @Override
1866 public String getLegacyKeyComparatorName() {
1867 return "org.apache.hadoop.hbase.KeyValue$MetaKeyComparator";
1868 }
1869
1870 @Override
1871 protected Object clone() throws CloneNotSupportedException {
1872 return new MetaComparator();
1873 }
1874
1875
1876
1877
1878 @Override
1879 protected int compareRowKey(final Cell l, final Cell r) {
1880 byte[] left = l.getRowArray();
1881 int loffset = l.getRowOffset();
1882 int llength = l.getRowLength();
1883 byte[] right = r.getRowArray();
1884 int roffset = r.getRowOffset();
1885 int rlength = r.getRowLength();
1886 return compareRows(left, loffset, llength, right, roffset, rlength);
1887 }
1888 }
1889
1890
1891
1892
1893
1894
1895 public static class KVComparator implements RawComparator<Cell>, SamePrefixComparator<byte[]> {
1896
1897
1898
1899
1900
1901
1902
1903 public String getLegacyKeyComparatorName() {
1904 return "org.apache.hadoop.hbase.KeyValue$KeyComparator";
1905 }
1906
1907 @Override
1908 public int compare(byte[] l, int loff, int llen, byte[] r, int roff, int rlen) {
1909 return compareFlatKey(l,loff,llen, r,roff,rlen);
1910 }
1911
1912
1913
1914
1915
1916
1917
1918
1919 protected int compareRowKey(final Cell left, final Cell right) {
1920 return CellComparator.compareRows(left, right);
1921 }
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934 public int compareFlatKey(byte[] left, int loffset, int llength,
1935 byte[] right, int roffset, int rlength) {
1936
1937 short lrowlength = Bytes.toShort(left, loffset);
1938 short rrowlength = Bytes.toShort(right, roffset);
1939 int compare = compareRows(left, loffset + Bytes.SIZEOF_SHORT,
1940 lrowlength, right, roffset + Bytes.SIZEOF_SHORT, rrowlength);
1941 if (compare != 0) {
1942 return compare;
1943 }
1944
1945
1946
1947
1948 return compareWithoutRow(0, left, loffset, llength, right, roffset,
1949 rlength, rrowlength);
1950 }
1951
1952 public int compareFlatKey(byte[] left, byte[] right) {
1953 return compareFlatKey(left, 0, left.length, right, 0, right.length);
1954 }
1955
1956
1957 public int compareKey(Cell cell,
1958 byte[] row, int roff, int rlen,
1959 byte[] fam, int foff, int flen,
1960 byte[] col, int coff, int clen,
1961 long ts, byte type) {
1962
1963 int compare = compareRows(
1964 cell.getRowArray(), cell.getRowOffset(), cell.getRowLength(),
1965 row, roff, rlen);
1966 if (compare != 0) {
1967 return compare;
1968 }
1969
1970
1971
1972
1973
1974 if (cell.getFamilyLength() + cell.getQualifierLength() == 0
1975 && cell.getTypeByte() == Type.Minimum.getCode()) {
1976
1977 return 1;
1978 }
1979 if (flen+clen == 0 && type == Type.Minimum.getCode()) {
1980 return -1;
1981 }
1982
1983 compare = compareFamilies(
1984 cell.getFamilyArray(), cell.getFamilyOffset(), cell.getFamilyLength(),
1985 fam, foff, flen);
1986 if (compare != 0) {
1987 return compare;
1988 }
1989 compare = compareColumns(
1990 cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength(),
1991 col, coff, clen);
1992 if (compare != 0) {
1993 return compare;
1994 }
1995
1996 compare = compareTimestamps(cell.getTimestamp(), ts);
1997 if (compare != 0) {
1998 return compare;
1999 }
2000
2001
2002
2003
2004
2005 return (0xff & type) - (0xff & cell.getTypeByte());
2006 }
2007
2008 public int compareOnlyKeyPortion(Cell left, Cell right) {
2009 return CellComparator.compare(left, right, true);
2010 }
2011
2012
2013
2014
2015
2016 @Override
2017 public int compare(final Cell left, final Cell right) {
2018 int compare = CellComparator.compare(left, right, false);
2019 return compare;
2020 }
2021
2022 public int compareTimestamps(final Cell left, final Cell right) {
2023 return CellComparator.compareTimestamps(left, right);
2024 }
2025
2026
2027
2028
2029
2030
2031 public int compareRows(final Cell left, final Cell right) {
2032 return compareRows(left.getRowArray(),left.getRowOffset(), left.getRowLength(),
2033 right.getRowArray(), right.getRowOffset(), right.getRowLength());
2034 }
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046 public int compareRows(byte [] left, int loffset, int llength,
2047 byte [] right, int roffset, int rlength) {
2048 return Bytes.compareTo(left, loffset, llength, right, roffset, rlength);
2049 }
2050
2051 int compareColumns(final Cell left, final short lrowlength, final Cell right,
2052 final short rrowlength) {
2053 return CellComparator.compareColumns(left, right);
2054 }
2055
2056 protected int compareColumns(
2057 byte [] left, int loffset, int llength, final int lfamilylength,
2058 byte [] right, int roffset, int rlength, final int rfamilylength) {
2059
2060 int diff = Bytes.compareTo(left, loffset, lfamilylength,
2061 right, roffset, rfamilylength);
2062 if (diff != 0) {
2063 return diff;
2064 }
2065
2066 return Bytes.compareTo(left, loffset + lfamilylength,
2067 llength - lfamilylength,
2068 right, roffset + rfamilylength, rlength - rfamilylength);
2069 }
2070
2071 static int compareTimestamps(final long ltimestamp, final long rtimestamp) {
2072
2073
2074
2075
2076 if (ltimestamp < rtimestamp) {
2077 return 1;
2078 } else if (ltimestamp > rtimestamp) {
2079 return -1;
2080 }
2081 return 0;
2082 }
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095 @Override
2096 public int compareIgnoringPrefix(int commonPrefix, byte[] left,
2097 int loffset, int llength, byte[] right, int roffset, int rlength) {
2098
2099 short lrowlength = Bytes.toShort(left, loffset);
2100 short rrowlength;
2101
2102 int comparisonResult = 0;
2103 if (commonPrefix < ROW_LENGTH_SIZE) {
2104
2105 rrowlength = Bytes.toShort(right, roffset);
2106 comparisonResult = compareRows(left, loffset + ROW_LENGTH_SIZE,
2107 lrowlength, right, roffset + ROW_LENGTH_SIZE, rrowlength);
2108 } else {
2109 rrowlength = lrowlength;
2110 if (commonPrefix < ROW_LENGTH_SIZE + rrowlength) {
2111
2112
2113 int common = commonPrefix - ROW_LENGTH_SIZE;
2114 comparisonResult = compareRows(
2115 left, loffset + common + ROW_LENGTH_SIZE, lrowlength - common,
2116 right, roffset + common + ROW_LENGTH_SIZE, rrowlength - common);
2117 }
2118 }
2119 if (comparisonResult != 0) {
2120 return comparisonResult;
2121 }
2122
2123 assert lrowlength == rrowlength;
2124 return compareWithoutRow(commonPrefix, left, loffset, llength, right,
2125 roffset, rlength, lrowlength);
2126 }
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138 private int compareWithoutRow(int commonPrefix, byte[] left, int loffset,
2139 int llength, byte[] right, int roffset, int rlength, short rowlength) {
2140
2141
2142
2143
2144
2145 int commonLength = ROW_LENGTH_SIZE + FAMILY_LENGTH_SIZE + rowlength;
2146
2147
2148 int commonLengthWithTSAndType = TIMESTAMP_TYPE_SIZE + commonLength;
2149
2150 int lcolumnlength = llength - commonLengthWithTSAndType;
2151 int rcolumnlength = rlength - commonLengthWithTSAndType;
2152
2153 byte ltype = left[loffset + (llength - 1)];
2154 byte rtype = right[roffset + (rlength - 1)];
2155
2156
2157
2158
2159
2160
2161 if (lcolumnlength == 0 && ltype == Type.Minimum.getCode()) {
2162
2163 return 1;
2164 }
2165 if (rcolumnlength == 0 && rtype == Type.Minimum.getCode()) {
2166 return -1;
2167 }
2168
2169 int lfamilyoffset = commonLength + loffset;
2170 int rfamilyoffset = commonLength + roffset;
2171
2172
2173 int lfamilylength = left[lfamilyoffset - 1];
2174 int rfamilylength = right[rfamilyoffset - 1];
2175
2176
2177 boolean sameFamilySize = (lfamilylength == rfamilylength);
2178 int common = 0;
2179 if (commonPrefix > 0) {
2180 common = Math.max(0, commonPrefix - commonLength);
2181 if (!sameFamilySize) {
2182
2183
2184 common = Math.min(common, Math.min(lfamilylength, rfamilylength));
2185 } else {
2186 common = Math.min(common, Math.min(lcolumnlength, rcolumnlength));
2187 }
2188 }
2189 if (!sameFamilySize) {
2190
2191 return Bytes.compareTo(left, lfamilyoffset + common, lfamilylength
2192 - common, right, rfamilyoffset + common, rfamilylength - common);
2193 }
2194
2195 final int comparison = Bytes.compareTo(left, lfamilyoffset + common,
2196 lcolumnlength - common, right, rfamilyoffset + common,
2197 rcolumnlength - common);
2198 if (comparison != 0) {
2199 return comparison;
2200 }
2201
2202
2203
2204 long ltimestamp = Bytes.toLong(left,
2205 loffset + (llength - TIMESTAMP_TYPE_SIZE));
2206 long rtimestamp = Bytes.toLong(right,
2207 roffset + (rlength - TIMESTAMP_TYPE_SIZE));
2208 int compare = compareTimestamps(ltimestamp, rtimestamp);
2209 if (compare != 0) {
2210 return compare;
2211 }
2212
2213
2214
2215
2216
2217 return (0xff & rtype) - (0xff & ltype);
2218 }
2219
2220 protected int compareFamilies(final byte[] left, final int loffset, final int lfamilylength,
2221 final byte[] right, final int roffset, final int rfamilylength) {
2222 int diff = Bytes.compareTo(left, loffset, lfamilylength, right, roffset, rfamilylength);
2223 return diff;
2224 }
2225
2226 protected int compareColumns(final byte[] left, final int loffset, final int lquallength,
2227 final byte[] right, final int roffset, final int rquallength) {
2228 int diff = Bytes.compareTo(left, loffset, lquallength, right, roffset, rquallength);
2229 return diff;
2230 }
2231
2232
2233
2234
2235
2236
2237 public boolean matchingRowColumn(final Cell left,
2238 final Cell right) {
2239 short lrowlength = left.getRowLength();
2240 short rrowlength = right.getRowLength();
2241
2242
2243 if ((left.getRowLength() + left.getFamilyLength() + left.getQualifierLength()) != (right
2244 .getRowLength() + right.getFamilyLength() + right.getQualifierLength())) {
2245 return false;
2246 }
2247
2248 if (!matchingRows(left, lrowlength, right, rrowlength)) {
2249 return false;
2250 }
2251
2252 int lfoffset = left.getFamilyOffset();
2253 int rfoffset = right.getFamilyOffset();
2254 int lclength = left.getQualifierLength();
2255 int rclength = right.getQualifierLength();
2256 int lfamilylength = left.getFamilyLength();
2257 int rfamilylength = right.getFamilyLength();
2258 int diff = compareFamilies(left.getFamilyArray(), lfoffset, lfamilylength,
2259 right.getFamilyArray(), rfoffset, rfamilylength);
2260 if (diff != 0) {
2261 return false;
2262 } else {
2263 diff = compareColumns(left.getQualifierArray(), left.getQualifierOffset(), lclength,
2264 right.getQualifierArray(), right.getQualifierOffset(), rclength);
2265 return diff == 0;
2266 }
2267 }
2268
2269
2270
2271
2272
2273
2274
2275 public boolean matchingRows(final Cell left, final Cell right) {
2276 short lrowlength = left.getRowLength();
2277 short rrowlength = right.getRowLength();
2278 return matchingRows(left, lrowlength, right, rrowlength);
2279 }
2280
2281
2282
2283
2284
2285
2286
2287
2288 private boolean matchingRows(final Cell left, final short lrowlength,
2289 final Cell right, final short rrowlength) {
2290 return lrowlength == rrowlength &&
2291 matchingRows(left.getRowArray(), left.getRowOffset(), lrowlength,
2292 right.getRowArray(), right.getRowOffset(), rrowlength);
2293 }
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305 public boolean matchingRows(final byte [] left, final int loffset, final int llength,
2306 final byte [] right, final int roffset, final int rlength) {
2307 return Bytes.equals(left, loffset, llength, right, roffset, rlength);
2308 }
2309
2310 public byte[] calcIndexKey(byte[] lastKeyOfPreviousBlock, byte[] firstKeyInBlock) {
2311 byte[] fakeKey = getShortMidpointKey(lastKeyOfPreviousBlock, firstKeyInBlock);
2312 if (compareFlatKey(fakeKey, firstKeyInBlock) > 0) {
2313 LOG.error("Unexpected getShortMidpointKey result, fakeKey:"
2314 + Bytes.toStringBinary(fakeKey) + ", firstKeyInBlock:"
2315 + Bytes.toStringBinary(firstKeyInBlock));
2316 return firstKeyInBlock;
2317 }
2318 if (lastKeyOfPreviousBlock != null && compareFlatKey(lastKeyOfPreviousBlock, fakeKey) >= 0) {
2319 LOG.error("Unexpected getShortMidpointKey result, lastKeyOfPreviousBlock:" +
2320 Bytes.toStringBinary(lastKeyOfPreviousBlock) + ", fakeKey:" +
2321 Bytes.toStringBinary(fakeKey));
2322 return firstKeyInBlock;
2323 }
2324 return fakeKey;
2325 }
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335 @Deprecated
2336 public byte[] getShortMidpointKey(final byte[] leftKey, final byte[] rightKey) {
2337 if (rightKey == null) {
2338 throw new IllegalArgumentException("rightKey can not be null");
2339 }
2340 if (leftKey == null) {
2341 return Arrays.copyOf(rightKey, rightKey.length);
2342 }
2343 if (compareFlatKey(leftKey, rightKey) >= 0) {
2344 throw new IllegalArgumentException("Unexpected input, leftKey:" + Bytes.toString(leftKey)
2345 + ", rightKey:" + Bytes.toString(rightKey));
2346 }
2347
2348 short leftRowLength = Bytes.toShort(leftKey, 0);
2349 short rightRowLength = Bytes.toShort(rightKey, 0);
2350 int leftCommonLength = ROW_LENGTH_SIZE + FAMILY_LENGTH_SIZE + leftRowLength;
2351 int rightCommonLength = ROW_LENGTH_SIZE + FAMILY_LENGTH_SIZE + rightRowLength;
2352 int leftCommonLengthWithTSAndType = TIMESTAMP_TYPE_SIZE + leftCommonLength;
2353 int rightCommonLengthWithTSAndType = TIMESTAMP_TYPE_SIZE + rightCommonLength;
2354 int leftColumnLength = leftKey.length - leftCommonLengthWithTSAndType;
2355 int rightColumnLength = rightKey.length - rightCommonLengthWithTSAndType;
2356
2357 if (leftRowLength == rightRowLength && compareRows(leftKey, ROW_LENGTH_SIZE, leftRowLength,
2358 rightKey, ROW_LENGTH_SIZE, rightRowLength) == 0) {
2359
2360 int comparison = Bytes.compareTo(leftKey, leftCommonLength, leftColumnLength, rightKey,
2361 rightCommonLength, rightColumnLength);
2362
2363 if (comparison == 0) {
2364 return Arrays.copyOf(rightKey, rightKey.length);
2365 }
2366
2367 byte[] newKey = Arrays.copyOf(rightKey, rightKey.length);
2368 Bytes.putLong(newKey, rightKey.length - TIMESTAMP_TYPE_SIZE, HConstants.LATEST_TIMESTAMP);
2369 Bytes.putByte(newKey, rightKey.length - TYPE_SIZE, Type.Maximum.getCode());
2370 return newKey;
2371 }
2372
2373 short minLength = leftRowLength < rightRowLength ? leftRowLength : rightRowLength;
2374 short diffIdx = 0;
2375 while (diffIdx < minLength
2376 && leftKey[ROW_LENGTH_SIZE + diffIdx] == rightKey[ROW_LENGTH_SIZE + diffIdx]) {
2377 diffIdx++;
2378 }
2379 byte[] newRowKey = null;
2380 if (diffIdx >= minLength) {
2381
2382 newRowKey = new byte[diffIdx + 1];
2383 System.arraycopy(rightKey, ROW_LENGTH_SIZE, newRowKey, 0, diffIdx + 1);
2384 } else {
2385 int diffByte = leftKey[ROW_LENGTH_SIZE + diffIdx];
2386 if ((0xff & diffByte) < 0xff && (diffByte + 1) <
2387 (rightKey[ROW_LENGTH_SIZE + diffIdx] & 0xff)) {
2388 newRowKey = new byte[diffIdx + 1];
2389 System.arraycopy(leftKey, ROW_LENGTH_SIZE, newRowKey, 0, diffIdx);
2390 newRowKey[diffIdx] = (byte) (diffByte + 1);
2391 } else {
2392 newRowKey = new byte[diffIdx + 1];
2393 System.arraycopy(rightKey, ROW_LENGTH_SIZE, newRowKey, 0, diffIdx + 1);
2394 }
2395 }
2396 return new KeyValue(newRowKey, null, null, HConstants.LATEST_TIMESTAMP,
2397 Type.Maximum).getKey();
2398 }
2399
2400 @Override
2401 protected Object clone() throws CloneNotSupportedException {
2402 super.clone();
2403 return new KVComparator();
2404 }
2405
2406 }
2407
2408
2409
2410
2411
2412
2413 public static KeyValue createKeyValueFromKey(final byte [] b) {
2414 return createKeyValueFromKey(b, 0, b.length);
2415 }
2416
2417
2418
2419
2420
2421
2422 public static KeyValue createKeyValueFromKey(final ByteBuffer bb) {
2423 return createKeyValueFromKey(bb.array(), bb.arrayOffset(), bb.limit());
2424 }
2425
2426
2427
2428
2429
2430
2431
2432
2433 public static KeyValue createKeyValueFromKey(final byte [] b, final int o,
2434 final int l) {
2435 byte [] newb = new byte[l + ROW_OFFSET];
2436 System.arraycopy(b, o, newb, ROW_OFFSET, l);
2437 Bytes.putInt(newb, 0, l);
2438 Bytes.putInt(newb, Bytes.SIZEOF_INT, 0);
2439 return new KeyValue(newb);
2440 }
2441
2442
2443
2444
2445
2446
2447
2448
2449 public static KeyValue create(final DataInput in) throws IOException {
2450 return create(in.readInt(), in);
2451 }
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461 public static KeyValue create(int length, final DataInput in) throws IOException {
2462
2463 if (length <= 0) {
2464 if (length == 0) return null;
2465 throw new IOException("Failed read " + length + " bytes, stream corrupt?");
2466 }
2467
2468
2469 byte [] bytes = new byte[length];
2470 in.readFully(bytes);
2471 return new KeyValue(bytes, 0, length);
2472 }
2473
2474
2475
2476
2477
2478
2479
2480 public static KeyValue cloneAndAddTags(Cell c, List<Tag> newTags) {
2481 List<Tag> existingTags = null;
2482 if(c.getTagsLength() > 0) {
2483 existingTags = Tag.asList(c.getTagsArray(), c.getTagsOffset(), c.getTagsLength());
2484 existingTags.addAll(newTags);
2485 } else {
2486 existingTags = newTags;
2487 }
2488 return new KeyValue(c.getRowArray(), c.getRowOffset(), (int)c.getRowLength(),
2489 c.getFamilyArray(), c.getFamilyOffset(), (int)c.getFamilyLength(),
2490 c.getQualifierArray(), c.getQualifierOffset(), (int) c.getQualifierLength(),
2491 c.getTimestamp(), Type.codeToType(c.getTypeByte()), c.getValueArray(), c.getValueOffset(),
2492 c.getValueLength(), existingTags);
2493 }
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503 @Deprecated
2504 public static KeyValue iscreate(final InputStream in) throws IOException {
2505 return KeyValueUtil.iscreate(in, true);
2506 }
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516 public static long write(final KeyValue kv, final DataOutput out) throws IOException {
2517
2518
2519 int length = kv.getLength();
2520 out.writeInt(length);
2521 out.write(kv.getBuffer(), kv.getOffset(), length);
2522 return length + Bytes.SIZEOF_INT;
2523 }
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537 @Deprecated
2538 public static long oswrite(final KeyValue kv, final OutputStream out)
2539 throws IOException {
2540 int length = kv.getLength();
2541
2542 out.write(Bytes.toBytes(length));
2543 out.write(kv.getBuffer(), kv.getOffset(), length);
2544 return length + Bytes.SIZEOF_INT;
2545 }
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560 public static long oswrite(final KeyValue kv, final OutputStream out, final boolean withTags)
2561 throws IOException {
2562
2563
2564 int length = kv.getLength();
2565 if (!withTags) {
2566 length = kv.getKeyLength() + kv.getValueLength() + KEYVALUE_INFRASTRUCTURE_SIZE;
2567 }
2568
2569 StreamUtils.writeInt(out, length);
2570 out.write(kv.getBuffer(), kv.getOffset(), length);
2571 return length + Bytes.SIZEOF_INT;
2572 }
2573
2574
2575
2576
2577 public static class RowOnlyComparator implements Comparator<KeyValue> {
2578 final KVComparator comparator;
2579
2580 public RowOnlyComparator(final KVComparator c) {
2581 this.comparator = c;
2582 }
2583
2584 @Override
2585 public int compare(KeyValue left, KeyValue right) {
2586 return comparator.compareRows(left, right);
2587 }
2588 }
2589
2590
2591
2592
2593
2594
2595
2596 public interface SamePrefixComparator<T> {
2597
2598
2599
2600
2601 int compareIgnoringPrefix(int commonPrefix, byte[] left, int loffset, int llength,
2602 byte[] right, int roffset, int rlength
2603 );
2604 }
2605
2606
2607
2608
2609 public static class RawBytesComparator extends KVComparator {
2610
2611
2612
2613
2614
2615
2616 @Override
2617 public String getLegacyKeyComparatorName() {
2618 return "org.apache.hadoop.hbase.util.Bytes$ByteArrayComparator";
2619 }
2620
2621
2622
2623
2624 @Override
2625 @Deprecated
2626 public int compareFlatKey(byte[] left, int loffset, int llength, byte[] right,
2627 int roffset, int rlength) {
2628 return Bytes.BYTES_RAWCOMPARATOR.compare(left, loffset, llength, right, roffset, rlength);
2629 }
2630
2631 @Override
2632 public int compare(Cell left, Cell right) {
2633 return compareOnlyKeyPortion(left, right);
2634 }
2635
2636 @Override
2637 @VisibleForTesting
2638 public int compareOnlyKeyPortion(Cell left, Cell right) {
2639 int c = Bytes.BYTES_RAWCOMPARATOR.compare(left.getRowArray(), left.getRowOffset(),
2640 left.getRowLength(), right.getRowArray(), right.getRowOffset(), right.getRowLength());
2641 if (c != 0) {
2642 return c;
2643 }
2644 c = Bytes.BYTES_RAWCOMPARATOR.compare(left.getFamilyArray(), left.getFamilyOffset(),
2645 left.getFamilyLength(), right.getFamilyArray(), right.getFamilyOffset(),
2646 right.getFamilyLength());
2647 if (c != 0) {
2648 return c;
2649 }
2650 c = Bytes.BYTES_RAWCOMPARATOR.compare(left.getQualifierArray(), left.getQualifierOffset(),
2651 left.getQualifierLength(), right.getQualifierArray(), right.getQualifierOffset(),
2652 right.getQualifierLength());
2653 if (c != 0) {
2654 return c;
2655 }
2656 c = compareTimestamps(left.getTimestamp(), right.getTimestamp());
2657 if (c != 0) {
2658 return c;
2659 }
2660 return (0xff & left.getTypeByte()) - (0xff & right.getTypeByte());
2661 }
2662
2663 @Override
2664 public byte[] calcIndexKey(byte[] lastKeyOfPreviousBlock, byte[] firstKeyInBlock) {
2665 return firstKeyInBlock;
2666 }
2667
2668 }
2669
2670
2671
2672
2673
2674
2675
2676 @Override
2677 public long heapSize() {
2678 int sum = 0;
2679 sum += ClassSize.OBJECT;
2680 sum += ClassSize.REFERENCE;
2681 sum += ClassSize.align(ClassSize.ARRAY);
2682 sum += ClassSize.align(length);
2683 sum += 2 * Bytes.SIZEOF_INT;
2684 sum += Bytes.SIZEOF_LONG;
2685 return ClassSize.align(sum);
2686 }
2687
2688
2689
2690
2691
2692
2693
2694
2695 @Deprecated
2696 public long heapSizeWithoutTags() {
2697 int sum = 0;
2698 sum += ClassSize.OBJECT;
2699 sum += ClassSize.REFERENCE;
2700 sum += ClassSize.align(ClassSize.ARRAY);
2701 sum += KeyValue.KEYVALUE_INFRASTRUCTURE_SIZE;
2702 sum += getKeyLength();
2703 sum += getValueLength();
2704 sum += 2 * Bytes.SIZEOF_INT;
2705 sum += Bytes.SIZEOF_LONG;
2706 return ClassSize.align(sum);
2707 }
2708
2709
2710
2711
2712
2713
2714
2715 public static class KeyOnlyKeyValue extends KeyValue {
2716 public KeyOnlyKeyValue() {
2717
2718 }
2719 public KeyOnlyKeyValue(byte[] b) {
2720 this(b, 0, b.length);
2721 }
2722
2723 public KeyOnlyKeyValue(byte[] b, int offset, int length) {
2724 this.bytes = b;
2725 this.length = length;
2726 this.offset = offset;
2727 }
2728
2729 @Override
2730 public int getKeyOffset() {
2731 return this.offset;
2732 }
2733
2734
2735
2736
2737
2738
2739
2740
2741 public void setKey(byte[] key, int offset, int length) {
2742 this.bytes = key;
2743 this.offset = offset;
2744 this.length = length;
2745 }
2746
2747 @Override
2748 public byte[] getKey() {
2749 int keylength = getKeyLength();
2750 byte[] key = new byte[keylength];
2751 System.arraycopy(this.bytes, getKeyOffset(), key, 0, keylength);
2752 return key;
2753 }
2754
2755 @Override
2756 public byte[] getRowArray() {
2757 return bytes;
2758 }
2759
2760 @Override
2761 public int getRowOffset() {
2762 return getKeyOffset() + Bytes.SIZEOF_SHORT;
2763 }
2764
2765 @Override
2766 public byte[] getFamilyArray() {
2767 return bytes;
2768 }
2769
2770 @Override
2771 public byte getFamilyLength() {
2772 return this.bytes[getFamilyOffset() - 1];
2773 }
2774
2775 @Override
2776 public int getFamilyOffset() {
2777 return this.offset + Bytes.SIZEOF_SHORT + getRowLength() + Bytes.SIZEOF_BYTE;
2778 }
2779
2780 @Override
2781 public byte[] getQualifierArray() {
2782 return bytes;
2783 }
2784
2785 @Override
2786 public int getQualifierLength() {
2787 return getQualifierLength(getRowLength(), getFamilyLength());
2788 }
2789
2790 @Override
2791 public int getQualifierOffset() {
2792 return getFamilyOffset() + getFamilyLength();
2793 }
2794
2795 @Override
2796 public int getKeyLength() {
2797 return length;
2798 }
2799
2800 @Override
2801 public short getRowLength() {
2802 return Bytes.toShort(this.bytes, getKeyOffset());
2803 }
2804
2805 @Override
2806 public byte getTypeByte() {
2807 return this.bytes[this.offset + getKeyLength() - 1];
2808 }
2809
2810 private int getQualifierLength(int rlength, int flength) {
2811 return getKeyLength() - (int) getKeyDataStructureSize(rlength, flength, 0);
2812 }
2813
2814 @Override
2815 public long getTimestamp() {
2816 int tsOffset = getTimestampOffset();
2817 return Bytes.toLong(this.bytes, tsOffset);
2818 }
2819
2820 @Override
2821 public int getTimestampOffset() {
2822 return getKeyOffset() + getKeyLength() - TIMESTAMP_TYPE_SIZE;
2823 }
2824
2825 @Override
2826 public byte[] getTagsArray() {
2827 return HConstants.EMPTY_BYTE_ARRAY;
2828 }
2829
2830 @Override
2831 public int getTagsOffset() {
2832 return 0;
2833 }
2834
2835 @Override
2836 public byte[] getValueArray() {
2837 throw new IllegalArgumentException("KeyOnlyKeyValue does not work with values.");
2838 }
2839
2840 @Override
2841 public int getValueOffset() {
2842 throw new IllegalArgumentException("KeyOnlyKeyValue does not work with values.");
2843 }
2844
2845 @Override
2846 public int getValueLength() {
2847 throw new IllegalArgumentException("KeyOnlyKeyValue does not work with values.");
2848 }
2849
2850 @Override
2851 public int getTagsLength() {
2852 return 0;
2853 }
2854
2855 @Override
2856 public String toString() {
2857 if (this.bytes == null || this.bytes.length == 0) {
2858 return "empty";
2859 }
2860 return keyToString(this.bytes, this.offset, getKeyLength()) + "/vlen=0/mvcc=0";
2861 }
2862
2863 @Override
2864 public int hashCode() {
2865 return super.hashCode();
2866 }
2867
2868 @Override
2869 public boolean equals(Object other) {
2870 return super.equals(other);
2871 }
2872 }
2873 }