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