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 return keyToString(k, 0, k.length);
717 }
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734 public Map<String, Object> toStringMap() {
735 Map<String, Object> stringMap = new HashMap<String, Object>();
736 stringMap.put("row", Bytes.toStringBinary(getRow()));
737 stringMap.put("family", Bytes.toStringBinary(getFamily()));
738 stringMap.put("qualifier", Bytes.toStringBinary(getQualifier()));
739 stringMap.put("timestamp", getTimestamp());
740 stringMap.put("vlen", getValueLength());
741 return stringMap;
742 }
743
744 public static String keyToString(final byte [] b, final int o, final int l) {
745 if (b == null) return "";
746 int rowlength = Bytes.toShort(b, o);
747 String row = Bytes.toStringBinary(b, o + Bytes.SIZEOF_SHORT, rowlength);
748 int columnoffset = o + Bytes.SIZEOF_SHORT + 1 + rowlength;
749 int familylength = b[columnoffset - 1];
750 int columnlength = l - ((columnoffset - o) + TIMESTAMP_TYPE_SIZE);
751 String family = familylength == 0? "":
752 Bytes.toStringBinary(b, columnoffset, familylength);
753 String qualifier = columnlength == 0? "":
754 Bytes.toStringBinary(b, columnoffset + familylength,
755 columnlength - familylength);
756 long timestamp = Bytes.toLong(b, o + (l - TIMESTAMP_TYPE_SIZE));
757 String timestampStr = humanReadableTimestamp(timestamp);
758 byte type = b[o + l - 1];
759 return row + "/" + family +
760 (family != null && family.length() > 0? ":" :"") +
761 qualifier + "/" + timestampStr + "/" + Type.codeToType(type);
762 }
763
764 public static String humanReadableTimestamp(final long timestamp) {
765 if (timestamp == HConstants.LATEST_TIMESTAMP) {
766 return "LATEST_TIMESTAMP";
767 }
768 if (timestamp == HConstants.OLDEST_TIMESTAMP) {
769 return "OLDEST_TIMESTAMP";
770 }
771 return String.valueOf(timestamp);
772 }
773
774
775
776
777
778
779
780
781
782
783 public byte [] getBuffer() {
784 return this.bytes;
785 }
786
787
788
789
790 public int getOffset() {
791 return this.offset;
792 }
793
794
795
796
797 public int getLength() {
798 return length;
799 }
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814 private static int getLength(byte [] bytes, int offset) {
815 return ROW_OFFSET +
816 Bytes.toInt(bytes, offset) +
817 Bytes.toInt(bytes, offset + Bytes.SIZEOF_INT);
818 }
819
820
821
822
823 public int getKeyOffset() {
824 return this.offset + ROW_OFFSET;
825 }
826
827 public String getKeyString() {
828 return Bytes.toStringBinary(getBuffer(), getKeyOffset(), getKeyLength());
829 }
830
831
832
833
834 private int keyLength = 0;
835
836 public int getKeyLength() {
837 if (keyLength == 0) {
838 keyLength = Bytes.toInt(this.bytes, this.offset);
839 }
840 return keyLength;
841 }
842
843
844
845
846 public int getValueOffset() {
847 return getKeyOffset() + getKeyLength();
848 }
849
850
851
852
853 public int getValueLength() {
854 return Bytes.toInt(this.bytes, this.offset + Bytes.SIZEOF_INT);
855 }
856
857
858
859
860 public int getRowOffset() {
861 return getKeyOffset() + Bytes.SIZEOF_SHORT;
862 }
863
864
865
866
867 public short getRowLength() {
868 return Bytes.toShort(this.bytes, getKeyOffset());
869 }
870
871
872
873
874 public int getFamilyOffset() {
875 return getFamilyOffset(getRowLength());
876 }
877
878
879
880
881 public int getFamilyOffset(int rlength) {
882 return this.offset + ROW_OFFSET + Bytes.SIZEOF_SHORT + rlength + Bytes.SIZEOF_BYTE;
883 }
884
885
886
887
888 public byte getFamilyLength() {
889 return getFamilyLength(getFamilyOffset());
890 }
891
892
893
894
895 public byte getFamilyLength(int foffset) {
896 return this.bytes[foffset-1];
897 }
898
899
900
901
902 public int getQualifierOffset() {
903 return getQualifierOffset(getFamilyOffset());
904 }
905
906
907
908
909 public int getQualifierOffset(int foffset) {
910 return foffset + getFamilyLength(foffset);
911 }
912
913
914
915
916 public int getQualifierLength() {
917 return getQualifierLength(getRowLength(),getFamilyLength());
918 }
919
920
921
922
923 public int getQualifierLength(int rlength, int flength) {
924 return getKeyLength() -
925 (KEY_INFRASTRUCTURE_SIZE + rlength + flength);
926 }
927
928
929
930
931 public int getTotalColumnLength() {
932 int rlength = getRowLength();
933 int foffset = getFamilyOffset(rlength);
934 return getTotalColumnLength(rlength,foffset);
935 }
936
937
938
939
940 public int getTotalColumnLength(int rlength, int foffset) {
941 int flength = getFamilyLength(foffset);
942 int qlength = getQualifierLength(rlength,flength);
943 return flength + qlength;
944 }
945
946
947
948
949 public int getTimestampOffset() {
950 return getTimestampOffset(getKeyLength());
951 }
952
953
954
955
956
957 public int getTimestampOffset(final int keylength) {
958 return getKeyOffset() + keylength - TIMESTAMP_TYPE_SIZE;
959 }
960
961
962
963
964 public boolean isLatestTimestamp() {
965 return Bytes.equals(getBuffer(), getTimestampOffset(), Bytes.SIZEOF_LONG,
966 HConstants.LATEST_TIMESTAMP_BYTES, 0, Bytes.SIZEOF_LONG);
967 }
968
969
970
971
972
973 public boolean isInternal() {
974 byte type = getType();
975 return type == Type.Minimum.code || type == Type.Maximum.code;
976 }
977
978
979
980
981
982 public boolean updateLatestStamp(final byte [] now) {
983 if (this.isLatestTimestamp()) {
984 int tsOffset = getTimestampOffset();
985 System.arraycopy(now, 0, this.bytes, tsOffset, Bytes.SIZEOF_LONG);
986
987 return true;
988 }
989 return false;
990 }
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005 public byte [] getKey() {
1006 int keylength = getKeyLength();
1007 byte [] key = new byte[keylength];
1008 System.arraycopy(getBuffer(), getKeyOffset(), key, 0, keylength);
1009 return key;
1010 }
1011
1012
1013
1014
1015
1016
1017
1018
1019 public byte [] getValue() {
1020 int o = getValueOffset();
1021 int l = getValueLength();
1022 byte [] result = new byte[l];
1023 System.arraycopy(getBuffer(), o, result, 0, l);
1024 return result;
1025 }
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035 public byte [] getRow() {
1036 int o = getRowOffset();
1037 short l = getRowLength();
1038 byte result[] = new byte[l];
1039 System.arraycopy(getBuffer(), o, result, 0, l);
1040 return result;
1041 }
1042
1043
1044
1045
1046
1047 public long getTimestamp() {
1048 return getTimestamp(getKeyLength());
1049 }
1050
1051
1052
1053
1054
1055 long getTimestamp(final int keylength) {
1056 int tsOffset = getTimestampOffset(keylength);
1057 return Bytes.toLong(this.bytes, tsOffset);
1058 }
1059
1060
1061
1062
1063 public byte getType() {
1064 return getType(getKeyLength());
1065 }
1066
1067
1068
1069
1070
1071 byte getType(final int keylength) {
1072 return this.bytes[this.offset + keylength - 1 + ROW_OFFSET];
1073 }
1074
1075
1076
1077
1078
1079
1080 public boolean isDelete() {
1081 return KeyValue.isDelete(getType());
1082 }
1083
1084
1085
1086
1087 public boolean isDeleteType() {
1088
1089 return getType() == Type.Delete.getCode();
1090 }
1091
1092
1093
1094
1095 public boolean isDeleteFamily() {
1096 return getType() == Type.DeleteFamily.getCode();
1097 }
1098
1099
1100
1101
1102
1103 public boolean isDeleteColumnOrFamily() {
1104 int t = getType();
1105 return t == Type.DeleteColumn.getCode() || t == Type.DeleteFamily.getCode();
1106 }
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116 public byte [] getFamily() {
1117 int o = getFamilyOffset();
1118 int l = getFamilyLength(o);
1119 byte [] result = new byte[l];
1120 System.arraycopy(this.bytes, o, result, 0, l);
1121 return result;
1122 }
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133 public byte [] getQualifier() {
1134 int o = getQualifierOffset();
1135 int l = getQualifierLength();
1136 byte [] result = new byte[l];
1137 System.arraycopy(this.bytes, o, result, 0, l);
1138 return result;
1139 }
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152 public static class SplitKeyValue {
1153 private byte [][] split;
1154 SplitKeyValue() {
1155 this.split = new byte[6][];
1156 }
1157 public void setRow(byte [] value) { this.split[0] = value; }
1158 public void setFamily(byte [] value) { this.split[1] = value; }
1159 public void setQualifier(byte [] value) { this.split[2] = value; }
1160 public void setTimestamp(byte [] value) { this.split[3] = value; }
1161 public void setType(byte [] value) { this.split[4] = value; }
1162 public void setValue(byte [] value) { this.split[5] = value; }
1163 public byte [] getRow() { return this.split[0]; }
1164 public byte [] getFamily() { return this.split[1]; }
1165 public byte [] getQualifier() { return this.split[2]; }
1166 public byte [] getTimestamp() { return this.split[3]; }
1167 public byte [] getType() { return this.split[4]; }
1168 public byte [] getValue() { return this.split[5]; }
1169 }
1170
1171 public SplitKeyValue split() {
1172 SplitKeyValue split = new SplitKeyValue();
1173 int splitOffset = this.offset;
1174 int keyLen = Bytes.toInt(bytes, splitOffset);
1175 splitOffset += Bytes.SIZEOF_INT;
1176 int valLen = Bytes.toInt(bytes, splitOffset);
1177 splitOffset += Bytes.SIZEOF_INT;
1178 short rowLen = Bytes.toShort(bytes, splitOffset);
1179 splitOffset += Bytes.SIZEOF_SHORT;
1180 byte [] row = new byte[rowLen];
1181 System.arraycopy(bytes, splitOffset, row, 0, rowLen);
1182 splitOffset += rowLen;
1183 split.setRow(row);
1184 byte famLen = bytes[splitOffset];
1185 splitOffset += Bytes.SIZEOF_BYTE;
1186 byte [] family = new byte[famLen];
1187 System.arraycopy(bytes, splitOffset, family, 0, famLen);
1188 splitOffset += famLen;
1189 split.setFamily(family);
1190 int colLen = keyLen -
1191 (rowLen + famLen + Bytes.SIZEOF_SHORT + Bytes.SIZEOF_BYTE +
1192 Bytes.SIZEOF_LONG + Bytes.SIZEOF_BYTE);
1193 byte [] qualifier = new byte[colLen];
1194 System.arraycopy(bytes, splitOffset, qualifier, 0, colLen);
1195 splitOffset += colLen;
1196 split.setQualifier(qualifier);
1197 byte [] timestamp = new byte[Bytes.SIZEOF_LONG];
1198 System.arraycopy(bytes, splitOffset, timestamp, 0, Bytes.SIZEOF_LONG);
1199 splitOffset += Bytes.SIZEOF_LONG;
1200 split.setTimestamp(timestamp);
1201 byte [] type = new byte[1];
1202 type[0] = bytes[splitOffset];
1203 splitOffset += Bytes.SIZEOF_BYTE;
1204 split.setType(type);
1205 byte [] value = new byte[valLen];
1206 System.arraycopy(bytes, splitOffset, value, 0, valLen);
1207 split.setValue(value);
1208 return split;
1209 }
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221 public boolean matchingFamily(final byte [] family) {
1222 return matchingFamily(family, 0, family.length);
1223 }
1224
1225 public boolean matchingFamily(final byte[] family, int offset, int length) {
1226 if (this.length == 0 || this.bytes.length == 0) {
1227 return false;
1228 }
1229 return Bytes.equals(family, offset, length,
1230 this.bytes, getFamilyOffset(), getFamilyLength());
1231 }
1232
1233 public boolean matchingFamily(final KeyValue other) {
1234 return matchingFamily(other.getBuffer(), other.getFamilyOffset(),
1235 other.getFamilyLength());
1236 }
1237
1238
1239
1240
1241
1242 public boolean matchingQualifier(final byte [] qualifier) {
1243 return matchingQualifier(qualifier, 0, qualifier.length);
1244 }
1245
1246 public boolean matchingQualifier(final byte [] qualifier, int offset, int length) {
1247 return Bytes.equals(qualifier, offset, length,
1248 this.bytes, getQualifierOffset(), getQualifierLength());
1249 }
1250
1251 public boolean matchingQualifier(final KeyValue other) {
1252 return matchingQualifier(other.getBuffer(), other.getQualifierOffset(),
1253 other.getQualifierLength());
1254 }
1255
1256 public boolean matchingRow(final byte [] row) {
1257 return matchingRow(row, 0, row.length);
1258 }
1259
1260 public boolean matchingRow(final byte[] row, int offset, int length) {
1261 return Bytes.equals(row, offset, length,
1262 this.bytes, getRowOffset(), getRowLength());
1263 }
1264
1265 public boolean matchingRow(KeyValue other) {
1266 return matchingRow(other.getBuffer(), other.getRowOffset(),
1267 other.getRowLength());
1268 }
1269
1270
1271
1272
1273
1274 public boolean matchingColumnNoDelimiter(final byte [] column) {
1275 int rl = getRowLength();
1276 int o = getFamilyOffset(rl);
1277 int fl = getFamilyLength(o);
1278 int l = fl + getQualifierLength(rl,fl);
1279 return Bytes.equals(column, 0, column.length, this.bytes, o, l);
1280 }
1281
1282
1283
1284
1285
1286
1287
1288 public boolean matchingColumn(final byte[] family, final byte[] qualifier) {
1289 int rl = getRowLength();
1290 int o = getFamilyOffset(rl);
1291 int fl = getFamilyLength(o);
1292 int ql = getQualifierLength(rl,fl);
1293 if (!Bytes.equals(family, 0, family.length, this.bytes, o, fl)) {
1294 return false;
1295 }
1296 if (qualifier == null || qualifier.length == 0) {
1297 if (ql == 0) {
1298 return true;
1299 }
1300 return false;
1301 }
1302 return Bytes.equals(qualifier, 0, qualifier.length,
1303 this.bytes, o + fl, ql);
1304 }
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317 static int compareColumns(final byte [] left, final int loffset,
1318 final int llength, final int lfamilylength,
1319 final byte [] right, final int roffset, final int rlength,
1320 final int rfamilylength) {
1321
1322 int diff = Bytes.compareTo(left, loffset, lfamilylength,
1323 right, roffset, rfamilylength);
1324 if (diff != 0) {
1325 return diff;
1326 }
1327
1328 return Bytes.compareTo(left, loffset + lfamilylength,
1329 llength - lfamilylength,
1330 right, roffset + rfamilylength, rlength - rfamilylength);
1331 }
1332
1333
1334
1335
1336 public boolean nonNullRowAndColumn() {
1337 return getRowLength() > 0 && !isEmptyColumn();
1338 }
1339
1340
1341
1342
1343 public boolean isEmptyColumn() {
1344 return getQualifierLength() == 0;
1345 }
1346
1347
1348
1349
1350
1351
1352 public KeyValue createKeyOnly(boolean lenAsVal) {
1353
1354
1355 int dataLen = lenAsVal? Bytes.SIZEOF_INT : 0;
1356 byte [] newBuffer = new byte[getKeyLength() + ROW_OFFSET + dataLen];
1357 System.arraycopy(this.bytes, this.offset, newBuffer, 0,
1358 Math.min(newBuffer.length,this.length));
1359 Bytes.putInt(newBuffer, Bytes.SIZEOF_INT, dataLen);
1360 if (lenAsVal) {
1361 Bytes.putInt(newBuffer, newBuffer.length - dataLen, this.getValueLength());
1362 }
1363 return new KeyValue(newBuffer);
1364 }
1365
1366
1367
1368
1369
1370
1371
1372
1373 public static byte [][] parseColumn(byte [] c) {
1374 final int index = getDelimiter(c, 0, c.length, COLUMN_FAMILY_DELIMITER);
1375 if (index == -1) {
1376
1377 return new byte [][] { c };
1378 } else if(index == c.length - 1) {
1379
1380 byte [] family = new byte[c.length-1];
1381 System.arraycopy(c, 0, family, 0, family.length);
1382 return new byte [][] { family };
1383 }
1384
1385 final byte [][] result = new byte [2][];
1386 result[0] = new byte [index];
1387 System.arraycopy(c, 0, result[0], 0, index);
1388 final int len = c.length - (index + 1);
1389 result[1] = new byte[len];
1390 System.arraycopy(c, index + 1
1391 len);
1392 return result;
1393 }
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403 public static byte [] makeColumn(byte [] family, byte [] qualifier) {
1404 return Bytes.add(family, COLUMN_FAMILY_DELIM_ARRAY, qualifier);
1405 }
1406
1407
1408
1409
1410
1411
1412 public static int getFamilyDelimiterIndex(final byte [] b, final int offset,
1413 final int length) {
1414 return getRequiredDelimiter(b, offset, length, COLUMN_FAMILY_DELIMITER);
1415 }
1416
1417 private static int getRequiredDelimiter(final byte [] b,
1418 final int offset, final int length, final int delimiter) {
1419 int index = getDelimiter(b, offset, length, delimiter);
1420 if (index < 0) {
1421 throw new IllegalArgumentException("No " + (char)delimiter + " in <" +
1422 Bytes.toString(b) + ">" + ", length=" + length + ", offset=" + offset);
1423 }
1424 return index;
1425 }
1426
1427
1428
1429
1430
1431 static int getRequiredDelimiterInReverse(final byte [] b,
1432 final int offset, final int length, final int delimiter) {
1433 int index = getDelimiterInReverse(b, offset, length, delimiter);
1434 if (index < 0) {
1435 throw new IllegalArgumentException(".META. key must have two '" + (char)delimiter + "' "
1436 + "delimiters and have the following format: '<table>,<key>,<etc>'");
1437 }
1438 return index;
1439 }
1440
1441
1442
1443
1444
1445
1446
1447 public static int getDelimiter(final byte [] b, int offset, final int length,
1448 final int delimiter) {
1449 if (b == null) {
1450 throw new IllegalArgumentException("Passed buffer is null");
1451 }
1452 int result = -1;
1453 for (int i = offset; i < length + offset; i++) {
1454 if (b[i] == delimiter) {
1455 result = i;
1456 break;
1457 }
1458 }
1459 return result;
1460 }
1461
1462
1463
1464
1465
1466
1467
1468 public static int getDelimiterInReverse(final byte [] b, final int offset,
1469 final int length, final int delimiter) {
1470 if (b == null) {
1471 throw new IllegalArgumentException("Passed buffer is null");
1472 }
1473 int result = -1;
1474 for (int i = (offset + length) - 1; i >= offset; i--) {
1475 if (b[i] == delimiter) {
1476 result = i;
1477 break;
1478 }
1479 }
1480 return result;
1481 }
1482
1483
1484
1485
1486
1487 public static class RootComparator extends MetaComparator {
1488 private final KeyComparator rawcomparator = new RootKeyComparator();
1489
1490 public KeyComparator getRawComparator() {
1491 return this.rawcomparator;
1492 }
1493
1494 @Override
1495 protected Object clone() throws CloneNotSupportedException {
1496 return new RootComparator();
1497 }
1498 }
1499
1500
1501
1502
1503
1504 public static class MetaComparator extends KVComparator {
1505 private final KeyComparator rawcomparator = new MetaKeyComparator();
1506
1507 public KeyComparator getRawComparator() {
1508 return this.rawcomparator;
1509 }
1510
1511 @Override
1512 protected Object clone() throws CloneNotSupportedException {
1513 return new MetaComparator();
1514 }
1515 }
1516
1517
1518
1519
1520
1521
1522
1523 public static class KVComparator implements java.util.Comparator<KeyValue> {
1524 private final KeyComparator rawcomparator = new KeyComparator();
1525
1526
1527
1528
1529
1530 public KeyComparator getRawComparator() {
1531 return this.rawcomparator;
1532 }
1533
1534 public int compare(final KeyValue left, final KeyValue right) {
1535 int ret = getRawComparator().compare(left.getBuffer(),
1536 left.getOffset() + ROW_OFFSET, left.getKeyLength(),
1537 right.getBuffer(), right.getOffset() + ROW_OFFSET,
1538 right.getKeyLength());
1539 if (ret != 0) return ret;
1540
1541 return -Longs.compare(left.getMemstoreTS(), right.getMemstoreTS());
1542 }
1543
1544 public int compareTimestamps(final KeyValue left, final KeyValue right) {
1545 return compareTimestamps(left, left.getKeyLength(), right,
1546 right.getKeyLength());
1547 }
1548
1549 int compareTimestamps(final KeyValue left, final int lkeylength,
1550 final KeyValue right, final int rkeylength) {
1551
1552 long ltimestamp = left.getTimestamp(lkeylength);
1553 long rtimestamp = right.getTimestamp(rkeylength);
1554 return getRawComparator().compareTimestamps(ltimestamp, rtimestamp);
1555 }
1556
1557
1558
1559
1560
1561
1562 public int compareRows(final KeyValue left, final KeyValue right) {
1563 return compareRows(left, left.getRowLength(), right,
1564 right.getRowLength());
1565 }
1566
1567
1568
1569
1570
1571
1572
1573
1574 public int compareRows(final KeyValue left, final short lrowlength,
1575 final KeyValue right, final short rrowlength) {
1576 return getRawComparator().compareRows(left.getBuffer(),
1577 left.getRowOffset(), lrowlength,
1578 right.getBuffer(), right.getRowOffset(), rrowlength);
1579 }
1580
1581
1582
1583
1584
1585
1586 public int compareRows(final KeyValue left, final byte [] row) {
1587 return getRawComparator().compareRows(left.getBuffer(),
1588 left.getRowOffset(), left.getRowLength(), row, 0, row.length);
1589 }
1590
1591 public int compareRows(byte [] left, int loffset, int llength,
1592 byte [] right, int roffset, int rlength) {
1593 return getRawComparator().compareRows(left, loffset, llength,
1594 right, roffset, rlength);
1595 }
1596
1597 public int compareColumns(final KeyValue left, final byte [] right,
1598 final int roffset, final int rlength, final int rfamilyoffset) {
1599 int offset = left.getFamilyOffset();
1600 int length = left.getFamilyLength() + left.getQualifierLength();
1601 return getRawComparator().compareColumns(left.getBuffer(), offset, length,
1602 left.getFamilyLength(offset),
1603 right, roffset, rlength, rfamilyoffset);
1604 }
1605
1606 int compareColumns(final KeyValue left, final short lrowlength,
1607 final KeyValue right, final short rrowlength) {
1608 int lfoffset = left.getFamilyOffset(lrowlength);
1609 int rfoffset = right.getFamilyOffset(rrowlength);
1610 int lclength = left.getTotalColumnLength(lrowlength,lfoffset);
1611 int rclength = right.getTotalColumnLength(rrowlength, rfoffset);
1612 int lfamilylength = left.getFamilyLength(lfoffset);
1613 int rfamilylength = right.getFamilyLength(rfoffset);
1614 return getRawComparator().compareColumns(left.getBuffer(), lfoffset,
1615 lclength, lfamilylength,
1616 right.getBuffer(), rfoffset, rclength, rfamilylength);
1617 }
1618
1619
1620
1621
1622
1623
1624
1625 public boolean matchingRowColumn(final KeyValue left,
1626 final KeyValue right) {
1627 short lrowlength = left.getRowLength();
1628 short rrowlength = right.getRowLength();
1629
1630 return ((left.getTimestampOffset() - left.getOffset()) ==
1631 (right.getTimestampOffset() - right.getOffset())) &&
1632 matchingRows(left, lrowlength, right, rrowlength) &&
1633 compareColumns(left, lrowlength, right, rrowlength) == 0;
1634 }
1635
1636
1637
1638
1639
1640
1641 public boolean matchingRows(final KeyValue left, final byte [] right) {
1642 return Bytes.equals(left.getBuffer(), left.getRowOffset(), left.getRowLength(),
1643 right, 0, right.length);
1644 }
1645
1646
1647
1648
1649
1650
1651
1652 public boolean matchingRows(final KeyValue left, final KeyValue right) {
1653 short lrowlength = left.getRowLength();
1654 short rrowlength = right.getRowLength();
1655 return matchingRows(left, lrowlength, right, rrowlength);
1656 }
1657
1658
1659
1660
1661
1662
1663
1664
1665 public boolean matchingRows(final KeyValue left, final short lrowlength,
1666 final KeyValue right, final short rrowlength) {
1667 return lrowlength == rrowlength &&
1668 Bytes.equals(left.getBuffer(), left.getRowOffset(), lrowlength,
1669 right.getBuffer(), right.getRowOffset(), rrowlength);
1670 }
1671
1672 public boolean matchingRows(final byte [] left, final int loffset,
1673 final int llength,
1674 final byte [] right, final int roffset, final int rlength) {
1675 return Bytes.equals(left, loffset, llength,
1676 right, roffset, rlength);
1677 }
1678
1679
1680
1681
1682
1683
1684
1685
1686 public boolean matchingRowsGreaterTimestamp(final KeyValue left,
1687 final KeyValue right) {
1688 short lrowlength = left.getRowLength();
1689 short rrowlength = right.getRowLength();
1690 if (!matchingRows(left, lrowlength, right, rrowlength)) {
1691 return false;
1692 }
1693 return left.getTimestamp() >= right.getTimestamp();
1694 }
1695
1696 @Override
1697 protected Object clone() throws CloneNotSupportedException {
1698 return new KVComparator();
1699 }
1700
1701
1702
1703
1704 public KVComparator getComparatorIgnoringTimestamps() {
1705 KVComparator c = null;
1706 try {
1707 c = (KVComparator)this.clone();
1708 c.getRawComparator().ignoreTimestamp = true;
1709 } catch (CloneNotSupportedException e) {
1710 LOG.error("Not supported", e);
1711 }
1712 return c;
1713 }
1714
1715
1716
1717
1718 public KVComparator getComparatorIgnoringType() {
1719 KVComparator c = null;
1720 try {
1721 c = (KVComparator)this.clone();
1722 c.getRawComparator().ignoreType = true;
1723 } catch (CloneNotSupportedException e) {
1724 LOG.error("Not supported", e);
1725 }
1726 return c;
1727 }
1728 }
1729
1730
1731
1732
1733
1734
1735
1736
1737 public static KeyValue createLastOnRow(final byte[] row) {
1738 return new KeyValue(row, null, null, HConstants.LATEST_TIMESTAMP, Type.Minimum);
1739 }
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749 public static KeyValue createFirstOnRow(final byte [] row) {
1750 return createFirstOnRow(row, HConstants.LATEST_TIMESTAMP);
1751 }
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761 public static KeyValue createFirstOnRow(final byte [] row, int roffset, short rlength) {
1762 return new KeyValue(row, roffset, rlength,
1763 null, 0, 0, null, 0, 0, HConstants.LATEST_TIMESTAMP, Type.Maximum, null, 0, 0);
1764 }
1765
1766
1767
1768
1769
1770
1771
1772
1773 public static KeyValue createFirstOnRow(final byte [] row,
1774 final long ts) {
1775 return new KeyValue(row, null, null, ts, Type.Maximum);
1776 }
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787 public static KeyValue createFirstOnRow(final byte [] row, final byte [] family,
1788 final byte [] qualifier) {
1789 return new KeyValue(row, family, qualifier, HConstants.LATEST_TIMESTAMP, Type.Maximum);
1790 }
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801 public static KeyValue createFirstDeleteFamilyOnRow(final byte [] row,
1802 final byte [] family) {
1803 return new KeyValue(row, family, null, HConstants.LATEST_TIMESTAMP,
1804 Type.DeleteFamily);
1805 }
1806
1807
1808
1809
1810
1811
1812
1813
1814 public static KeyValue createFirstOnRow(final byte [] row, final byte [] f,
1815 final byte [] q, final long ts) {
1816 return new KeyValue(row, f, q, ts, Type.Maximum);
1817 }
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835 public static KeyValue createFirstOnRow(final byte [] row,
1836 final int roffset, final int rlength, final byte [] family,
1837 final int foffset, final int flength, final byte [] qualifier,
1838 final int qoffset, final int qlength) {
1839 return new KeyValue(row, roffset, rlength, family,
1840 foffset, flength, qualifier, qoffset, qlength,
1841 HConstants.LATEST_TIMESTAMP, Type.Maximum, null, 0, 0);
1842 }
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860 public static KeyValue createLastOnRow(final byte [] row,
1861 final int roffset, final int rlength, final byte [] family,
1862 final int foffset, final int flength, final byte [] qualifier,
1863 final int qoffset, final int qlength) {
1864 return new KeyValue(row, roffset, rlength, family,
1865 foffset, flength, qualifier, qoffset, qlength,
1866 HConstants.OLDEST_TIMESTAMP, Type.Minimum, null, 0, 0);
1867 }
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877 public KeyValue createLastOnRowCol() {
1878 return new KeyValue(
1879 bytes, getRowOffset(), getRowLength(),
1880 bytes, getFamilyOffset(), getFamilyLength(),
1881 bytes, getQualifierOffset(), getQualifierLength(),
1882 HConstants.OLDEST_TIMESTAMP, Type.Minimum, null, 0, 0);
1883 }
1884
1885
1886
1887
1888
1889
1890
1891
1892 public KeyValue createFirstOnRowColTS(long ts) {
1893 return new KeyValue(
1894 bytes, getRowOffset(), getRowLength(),
1895 bytes, getFamilyOffset(), getFamilyLength(),
1896 bytes, getQualifierOffset(), getQualifierLength(),
1897 ts, Type.Maximum, bytes, getValueOffset(), getValueLength());
1898 }
1899
1900
1901
1902
1903
1904
1905 public static KeyValue createKeyValueFromKey(final byte [] b) {
1906 return createKeyValueFromKey(b, 0, b.length);
1907 }
1908
1909
1910
1911
1912
1913
1914 public static KeyValue createKeyValueFromKey(final ByteBuffer bb) {
1915 return createKeyValueFromKey(bb.array(), bb.arrayOffset(), bb.limit());
1916 }
1917
1918
1919
1920
1921
1922
1923
1924
1925 public static KeyValue createKeyValueFromKey(final byte [] b, final int o,
1926 final int l) {
1927 byte [] newb = new byte[l + ROW_OFFSET];
1928 System.arraycopy(b, o, newb, ROW_OFFSET, l);
1929 Bytes.putInt(newb, 0, l);
1930 Bytes.putInt(newb, Bytes.SIZEOF_INT, 0);
1931 return new KeyValue(newb);
1932 }
1933
1934
1935
1936
1937
1938 public static class RootKeyComparator extends MetaKeyComparator {
1939 public int compareRows(byte [] left, int loffset, int llength,
1940 byte [] right, int roffset, int rlength) {
1941
1942
1943
1944 final int metalength = 7;
1945 int lmetaOffsetPlusDelimiter = loffset + metalength;
1946 int leftFarDelimiter = getDelimiterInReverse(left,
1947 lmetaOffsetPlusDelimiter,
1948 llength - metalength, HRegionInfo.DELIMITER);
1949 int rmetaOffsetPlusDelimiter = roffset + metalength;
1950 int rightFarDelimiter = getDelimiterInReverse(right,
1951 rmetaOffsetPlusDelimiter, rlength - metalength,
1952 HRegionInfo.DELIMITER);
1953 if (leftFarDelimiter < 0 && rightFarDelimiter >= 0) {
1954
1955 return -1;
1956 } else if (rightFarDelimiter < 0 && leftFarDelimiter >= 0) {
1957 return 1;
1958 } else if (leftFarDelimiter < 0 && rightFarDelimiter < 0) {
1959 return 0;
1960 }
1961 int result = super.compareRows(left, lmetaOffsetPlusDelimiter,
1962 leftFarDelimiter - lmetaOffsetPlusDelimiter,
1963 right, rmetaOffsetPlusDelimiter,
1964 rightFarDelimiter - rmetaOffsetPlusDelimiter);
1965 if (result != 0) {
1966 return result;
1967 }
1968
1969 leftFarDelimiter++;
1970 rightFarDelimiter++;
1971 result = compareRowid(left, leftFarDelimiter,
1972 llength - (leftFarDelimiter - loffset),
1973 right, rightFarDelimiter, rlength - (rightFarDelimiter - roffset));
1974 return result;
1975 }
1976 }
1977
1978
1979
1980
1981 public static class RowComparator implements Comparator<KeyValue> {
1982 final KVComparator comparator;
1983
1984 public RowComparator(final KVComparator c) {
1985 this.comparator = c;
1986 }
1987
1988 public int compare(KeyValue left, KeyValue right) {
1989 return comparator.compareRows(left, right);
1990 }
1991 }
1992
1993
1994
1995
1996
1997 public static class MetaKeyComparator extends KeyComparator {
1998 public int compareRows(byte [] left, int loffset, int llength,
1999 byte [] right, int roffset, int rlength) {
2000
2001
2002 int leftDelimiter = getDelimiter(left, loffset, llength,
2003 HRegionInfo.DELIMITER);
2004 int rightDelimiter = getDelimiter(right, roffset, rlength,
2005 HRegionInfo.DELIMITER);
2006 if (leftDelimiter < 0 && rightDelimiter >= 0) {
2007
2008 return -1;
2009 } else if (rightDelimiter < 0 && leftDelimiter >= 0) {
2010 return 1;
2011 } else if (leftDelimiter < 0 && rightDelimiter < 0) {
2012 return 0;
2013 }
2014
2015 int result = Bytes.compareTo(left, loffset, leftDelimiter - loffset,
2016 right, roffset, rightDelimiter - roffset);
2017 if (result != 0) {
2018 return result;
2019 }
2020
2021
2022 leftDelimiter++;
2023 rightDelimiter++;
2024 int leftFarDelimiter = getRequiredDelimiterInReverse(left, leftDelimiter,
2025 llength - (leftDelimiter - loffset), HRegionInfo.DELIMITER);
2026 int rightFarDelimiter = getRequiredDelimiterInReverse(right,
2027 rightDelimiter, rlength - (rightDelimiter - roffset),
2028 HRegionInfo.DELIMITER);
2029
2030 result = super.compareRows(left, leftDelimiter,
2031 leftFarDelimiter - leftDelimiter, right, rightDelimiter,
2032 rightFarDelimiter - rightDelimiter);
2033 if (result != 0) {
2034 return result;
2035 }
2036
2037 leftFarDelimiter++;
2038 rightFarDelimiter++;
2039 result = compareRowid(left, leftFarDelimiter,
2040 llength - (leftFarDelimiter - loffset),
2041 right, rightFarDelimiter, rlength - (rightFarDelimiter - roffset));
2042 return result;
2043 }
2044
2045 protected int compareRowid(byte[] left, int loffset, int llength,
2046 byte[] right, int roffset, int rlength) {
2047 return Bytes.compareTo(left, loffset, llength, right, roffset, rlength);
2048 }
2049 }
2050
2051
2052
2053
2054 public static interface SamePrefixComparator<T> {
2055
2056
2057
2058
2059 public int compareIgnoringPrefix(int commonPrefix,
2060 T left, int loffset, int llength,
2061 T right, int roffset, int rlength);
2062 }
2063
2064
2065
2066
2067 public static class KeyComparator
2068 implements RawComparator<byte []>, SamePrefixComparator<byte[]> {
2069 volatile boolean ignoreTimestamp = false;
2070 volatile boolean ignoreType = false;
2071
2072 public int compare(byte[] left, int loffset, int llength, byte[] right,
2073 int roffset, int rlength) {
2074
2075 short lrowlength = Bytes.toShort(left, loffset);
2076 short rrowlength = Bytes.toShort(right, roffset);
2077 int compare = compareRows(left, loffset + Bytes.SIZEOF_SHORT,
2078 lrowlength, right, roffset + Bytes.SIZEOF_SHORT, rrowlength);
2079 if (compare != 0) {
2080 return compare;
2081 }
2082
2083
2084
2085
2086 return compareWithoutRow(0, left, loffset, llength, right, roffset,
2087 rlength, rrowlength);
2088 }
2089
2090
2091
2092
2093
2094
2095 @Override
2096 public int compareIgnoringPrefix(int commonPrefix, byte[] left,
2097 int loffset, int llength, byte[] right, int roffset, int rlength) {
2098
2099 short lrowlength = Bytes.toShort(left, loffset);
2100 short rrowlength;
2101
2102 int comparisonResult = 0;
2103 if (commonPrefix < ROW_LENGTH_SIZE) {
2104
2105 rrowlength = Bytes.toShort(right, roffset);
2106 comparisonResult = compareRows(left, loffset + ROW_LENGTH_SIZE,
2107 lrowlength, right, roffset + ROW_LENGTH_SIZE, rrowlength);
2108 } else {
2109 rrowlength = lrowlength;
2110 if (commonPrefix < ROW_LENGTH_SIZE + rrowlength) {
2111
2112
2113 int common = commonPrefix - ROW_LENGTH_SIZE;
2114 comparisonResult = compareRows(
2115 left, loffset + common + ROW_LENGTH_SIZE, lrowlength - common,
2116 right, roffset + common + ROW_LENGTH_SIZE, rrowlength - common);
2117 }
2118 }
2119 if (comparisonResult != 0) {
2120 return comparisonResult;
2121 }
2122
2123 assert lrowlength == rrowlength;
2124
2125 return compareWithoutRow(commonPrefix, left, loffset, llength, right,
2126 roffset, rlength, lrowlength);
2127 }
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139 private int compareWithoutRow(int commonPrefix, byte[] left, int loffset,
2140 int llength, byte[] right, int roffset, int rlength, short rowlength) {
2141
2142
2143
2144
2145
2146 int commonLength = ROW_LENGTH_SIZE + FAMILY_LENGTH_SIZE + rowlength;
2147
2148
2149 int commonLengthWithTSAndType = TIMESTAMP_TYPE_SIZE + commonLength;
2150
2151 int lcolumnlength = llength - commonLengthWithTSAndType;
2152 int rcolumnlength = rlength - commonLengthWithTSAndType;
2153
2154 byte ltype = left[loffset + (llength - 1)];
2155 byte rtype = right[roffset + (rlength - 1)];
2156
2157
2158
2159
2160
2161
2162 if (lcolumnlength == 0 && ltype == Type.Minimum.getCode()) {
2163
2164 return 1;
2165 }
2166 if (rcolumnlength == 0 && rtype == Type.Minimum.getCode()) {
2167 return -1;
2168 }
2169
2170 int lfamilyoffset = commonLength + loffset;
2171 int rfamilyoffset = commonLength + roffset;
2172
2173
2174 int lfamilylength = left[lfamilyoffset - 1];
2175 int rfamilylength = right[rfamilyoffset - 1];
2176
2177
2178 boolean sameFamilySize = (lfamilylength == rfamilylength);
2179 int common = 0;
2180 if (commonPrefix > 0) {
2181 common = Math.max(0, commonPrefix - commonLength);
2182 if (!sameFamilySize) {
2183
2184
2185 common = Math.min(common, Math.min(lfamilylength, rfamilylength));
2186 } else {
2187 common = Math.min(common, Math.min(lcolumnlength, rcolumnlength));
2188 }
2189 }
2190 if (!sameFamilySize) {
2191
2192 return Bytes.compareTo(left, lfamilyoffset + common, lfamilylength
2193 - common, right, rfamilyoffset + common, rfamilylength - common);
2194 }
2195
2196 final int comparison = Bytes.compareTo(left, lfamilyoffset + common,
2197 lcolumnlength - common, right, rfamilyoffset + common,
2198 rcolumnlength - common);
2199 if (comparison != 0) {
2200 return comparison;
2201 }
2202 return compareTimestampAndType(left, loffset, llength, right, roffset,
2203 rlength, ltype, rtype);
2204 }
2205
2206 private int compareTimestampAndType(byte[] left, int loffset, int llength,
2207 byte[] right, int roffset, int rlength, byte ltype, byte rtype) {
2208 int compare;
2209 if (!this.ignoreTimestamp) {
2210
2211 long ltimestamp = Bytes.toLong(left,
2212 loffset + (llength - TIMESTAMP_TYPE_SIZE));
2213 long rtimestamp = Bytes.toLong(right,
2214 roffset + (rlength - TIMESTAMP_TYPE_SIZE));
2215 compare = compareTimestamps(ltimestamp, rtimestamp);
2216 if (compare != 0) {
2217 return compare;
2218 }
2219 }
2220
2221 if (!this.ignoreType) {
2222
2223
2224
2225
2226 return (0xff & rtype) - (0xff & ltype);
2227 }
2228 return 0;
2229 }
2230
2231 public int compare(byte[] left, byte[] right) {
2232 return compare(left, 0, left.length, right, 0, right.length);
2233 }
2234
2235 public int compareRows(byte [] left, int loffset, int llength,
2236 byte [] right, int roffset, int rlength) {
2237 return Bytes.compareTo(left, loffset, llength, right, roffset, rlength);
2238 }
2239
2240 protected int compareColumns(
2241 byte [] left, int loffset, int llength, final int lfamilylength,
2242 byte [] right, int roffset, int rlength, final int rfamilylength) {
2243 return KeyValue.compareColumns(left, loffset, llength, lfamilylength,
2244 right, roffset, rlength, rfamilylength);
2245 }
2246
2247 int compareTimestamps(final long ltimestamp, final long rtimestamp) {
2248
2249
2250
2251
2252 if (ltimestamp < rtimestamp) {
2253 return 1;
2254 } else if (ltimestamp > rtimestamp) {
2255 return -1;
2256 }
2257 return 0;
2258 }
2259 }
2260
2261
2262 public long heapSize() {
2263 return ClassSize.align(ClassSize.OBJECT + ClassSize.REFERENCE
2264 + ClassSize.align(ClassSize.ARRAY) + ClassSize.align(length)
2265 + (3 * Bytes.SIZEOF_INT) + Bytes.SIZEOF_LONG);
2266 }
2267
2268
2269
2270
2271 public void readFields(int length, final DataInput in) throws IOException {
2272 this.length = length;
2273 this.offset = 0;
2274 this.keyLength = 0;
2275 this.bytes = new byte[this.length];
2276 in.readFully(this.bytes, 0, this.length);
2277 }
2278
2279
2280 public void readFields(final DataInput in) throws IOException {
2281 int length = in.readInt();
2282 readFields(length, in);
2283 }
2284
2285 public void write(final DataOutput out) throws IOException {
2286 out.writeInt(this.length);
2287 out.write(this.bytes, this.offset, this.length);
2288 }
2289 }