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