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