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