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