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