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