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