1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase;
20
21 import java.io.DataInput;
22 import java.io.DataOutput;
23 import java.io.IOException;
24 import java.util.Collections;
25 import java.util.HashMap;
26 import java.util.HashSet;
27 import java.util.Map;
28 import java.util.Set;
29
30 import org.apache.hadoop.hbase.classification.InterfaceAudience;
31 import org.apache.hadoop.hbase.classification.InterfaceStability;
32 import org.apache.hadoop.hbase.exceptions.DeserializationException;
33 import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
34 import org.apache.hadoop.hbase.io.compress.Compression;
35 import org.apache.hadoop.hbase.io.encoding.DataBlockEncoding;
36 import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
37 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.BytesBytesPair;
38 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.ColumnFamilySchema;
39 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.NameStringPair;
40 import org.apache.hadoop.hbase.regionserver.BloomType;
41 import org.apache.hadoop.hbase.util.Bytes;
42 import org.apache.hadoop.hbase.util.PrettyPrinter;
43 import org.apache.hadoop.hbase.util.PrettyPrinter.Unit;
44 import org.apache.hadoop.io.Text;
45 import org.apache.hadoop.io.WritableComparable;
46
47 import com.google.common.base.Preconditions;
48 import org.apache.hadoop.hbase.util.ByteStringer;
49
50
51
52
53
54
55
56 @InterfaceAudience.Public
57 @InterfaceStability.Evolving
58 public class HColumnDescriptor implements WritableComparable<HColumnDescriptor> {
59
60
61
62
63
64
65
66
67
68
69
70 private static final byte COLUMN_DESCRIPTOR_VERSION = (byte) 11;
71
72
73 public static final String COMPRESSION = "COMPRESSION";
74 public static final String COMPRESSION_COMPACT = "COMPRESSION_COMPACT";
75 public static final String ENCODE_ON_DISK =
76 "ENCODE_ON_DISK";
77 public static final String DATA_BLOCK_ENCODING =
78 "DATA_BLOCK_ENCODING";
79
80
81
82
83
84
85 public static final String BLOCKCACHE = "BLOCKCACHE";
86 public static final String CACHE_DATA_ON_WRITE = "CACHE_DATA_ON_WRITE";
87 public static final String CACHE_INDEX_ON_WRITE = "CACHE_INDEX_ON_WRITE";
88 public static final String CACHE_BLOOMS_ON_WRITE = "CACHE_BLOOMS_ON_WRITE";
89 public static final String EVICT_BLOCKS_ON_CLOSE = "EVICT_BLOCKS_ON_CLOSE";
90
91
92
93
94
95
96 public static final String CACHE_DATA_IN_L1 = "CACHE_DATA_IN_L1";
97
98
99
100
101
102
103
104 public static final String PREFETCH_BLOCKS_ON_OPEN = "PREFETCH_BLOCKS_ON_OPEN";
105
106
107
108
109
110
111 public static final String BLOCKSIZE = "BLOCKSIZE";
112
113 public static final String LENGTH = "LENGTH";
114 public static final String TTL = "TTL";
115 public static final String BLOOMFILTER = "BLOOMFILTER";
116 public static final String FOREVER = "FOREVER";
117 public static final String REPLICATION_SCOPE = "REPLICATION_SCOPE";
118 public static final byte[] REPLICATION_SCOPE_BYTES = Bytes.toBytes(REPLICATION_SCOPE);
119 public static final String MIN_VERSIONS = "MIN_VERSIONS";
120 public static final String KEEP_DELETED_CELLS = "KEEP_DELETED_CELLS";
121 public static final String COMPRESS_TAGS = "COMPRESS_TAGS";
122
123 public static final String ENCRYPTION = "ENCRYPTION";
124 public static final String ENCRYPTION_KEY = "ENCRYPTION_KEY";
125
126 public static final String IS_MOB = "IS_MOB";
127 public static final byte[] IS_MOB_BYTES = Bytes.toBytes(IS_MOB);
128 public static final String MOB_THRESHOLD = "MOB_THRESHOLD";
129 public static final byte[] MOB_THRESHOLD_BYTES = Bytes.toBytes(MOB_THRESHOLD);
130 public static final long DEFAULT_MOB_THRESHOLD = 100 * 1024;
131
132 public static final String DFS_REPLICATION = "DFS_REPLICATION";
133 public static final short DEFAULT_DFS_REPLICATION = 0;
134
135
136
137
138 public static final String DEFAULT_COMPRESSION =
139 Compression.Algorithm.NONE.getName();
140
141
142
143
144
145
146 public static final boolean DEFAULT_ENCODE_ON_DISK = true;
147
148
149 public static final String DEFAULT_DATA_BLOCK_ENCODING =
150 DataBlockEncoding.NONE.toString();
151
152
153
154
155 public static final int DEFAULT_VERSIONS = HBaseConfiguration.create().getInt(
156 "hbase.column.max.version", 1);
157
158
159
160
161 public static final int DEFAULT_MIN_VERSIONS = 0;
162
163
164
165
166
167 private volatile Integer blocksize = null;
168
169
170
171
172 public static final boolean DEFAULT_IN_MEMORY = false;
173
174
175
176
177 public static final KeepDeletedCells DEFAULT_KEEP_DELETED = KeepDeletedCells.FALSE;
178
179
180
181
182 public static final boolean DEFAULT_BLOCKCACHE = true;
183
184
185
186
187
188 public static final boolean DEFAULT_CACHE_DATA_ON_WRITE = false;
189
190
191
192
193
194
195 public static final boolean DEFAULT_CACHE_DATA_IN_L1 = false;
196
197
198
199
200
201 public static final boolean DEFAULT_CACHE_INDEX_ON_WRITE = false;
202
203
204
205
206 public static final int DEFAULT_BLOCKSIZE = HConstants.DEFAULT_BLOCKSIZE;
207
208
209
210
211 public static final String DEFAULT_BLOOMFILTER = BloomType.ROW.toString();
212
213
214
215
216
217 public static final boolean DEFAULT_CACHE_BLOOMS_ON_WRITE = false;
218
219
220
221
222 public static final int DEFAULT_TTL = HConstants.FOREVER;
223
224
225
226
227 public static final int DEFAULT_REPLICATION_SCOPE = HConstants.REPLICATION_SCOPE_LOCAL;
228
229
230
231
232
233 public static final boolean DEFAULT_EVICT_BLOCKS_ON_CLOSE = false;
234
235
236
237
238 public static final boolean DEFAULT_COMPRESS_TAGS = true;
239
240
241
242
243 public static final boolean DEFAULT_PREFETCH_BLOCKS_ON_OPEN = false;
244
245 private final static Map<String, String> DEFAULT_VALUES
246 = new HashMap<String, String>();
247 private final static Set<ImmutableBytesWritable> RESERVED_KEYWORDS
248 = new HashSet<ImmutableBytesWritable>();
249 static {
250 DEFAULT_VALUES.put(BLOOMFILTER, DEFAULT_BLOOMFILTER);
251 DEFAULT_VALUES.put(REPLICATION_SCOPE, String.valueOf(DEFAULT_REPLICATION_SCOPE));
252 DEFAULT_VALUES.put(HConstants.VERSIONS, String.valueOf(DEFAULT_VERSIONS));
253 DEFAULT_VALUES.put(MIN_VERSIONS, String.valueOf(DEFAULT_MIN_VERSIONS));
254 DEFAULT_VALUES.put(COMPRESSION, DEFAULT_COMPRESSION);
255 DEFAULT_VALUES.put(TTL, String.valueOf(DEFAULT_TTL));
256 DEFAULT_VALUES.put(BLOCKSIZE, String.valueOf(DEFAULT_BLOCKSIZE));
257 DEFAULT_VALUES.put(HConstants.IN_MEMORY, String.valueOf(DEFAULT_IN_MEMORY));
258 DEFAULT_VALUES.put(BLOCKCACHE, String.valueOf(DEFAULT_BLOCKCACHE));
259 DEFAULT_VALUES.put(KEEP_DELETED_CELLS, String.valueOf(DEFAULT_KEEP_DELETED));
260 DEFAULT_VALUES.put(DATA_BLOCK_ENCODING, String.valueOf(DEFAULT_DATA_BLOCK_ENCODING));
261 DEFAULT_VALUES.put(CACHE_DATA_ON_WRITE, String.valueOf(DEFAULT_CACHE_DATA_ON_WRITE));
262 DEFAULT_VALUES.put(CACHE_DATA_IN_L1, String.valueOf(DEFAULT_CACHE_DATA_IN_L1));
263 DEFAULT_VALUES.put(CACHE_INDEX_ON_WRITE, String.valueOf(DEFAULT_CACHE_INDEX_ON_WRITE));
264 DEFAULT_VALUES.put(CACHE_BLOOMS_ON_WRITE, String.valueOf(DEFAULT_CACHE_BLOOMS_ON_WRITE));
265 DEFAULT_VALUES.put(EVICT_BLOCKS_ON_CLOSE, String.valueOf(DEFAULT_EVICT_BLOCKS_ON_CLOSE));
266 DEFAULT_VALUES.put(PREFETCH_BLOCKS_ON_OPEN, String.valueOf(DEFAULT_PREFETCH_BLOCKS_ON_OPEN));
267 for (String s : DEFAULT_VALUES.keySet()) {
268 RESERVED_KEYWORDS.add(new ImmutableBytesWritable(Bytes.toBytes(s)));
269 }
270 RESERVED_KEYWORDS.add(new ImmutableBytesWritable(Bytes.toBytes(ENCRYPTION)));
271 RESERVED_KEYWORDS.add(new ImmutableBytesWritable(Bytes.toBytes(ENCRYPTION_KEY)));
272 RESERVED_KEYWORDS.add(new ImmutableBytesWritable(IS_MOB_BYTES));
273 RESERVED_KEYWORDS.add(new ImmutableBytesWritable(MOB_THRESHOLD_BYTES));
274 }
275
276 private static final int UNINITIALIZED = -1;
277
278
279 private byte [] name;
280
281
282 private final Map<ImmutableBytesWritable, ImmutableBytesWritable> values =
283 new HashMap<ImmutableBytesWritable,ImmutableBytesWritable>();
284
285
286
287
288
289
290 private final Map<String, String> configuration = new HashMap<String, String>();
291
292
293
294
295 private int cachedMaxVersions = UNINITIALIZED;
296
297
298
299
300
301
302
303
304 @Deprecated
305
306
307 public HColumnDescriptor() {
308 this.name = null;
309 }
310
311
312
313
314
315
316
317
318 public HColumnDescriptor(final String familyName) {
319 this(Bytes.toBytes(familyName));
320 }
321
322
323
324
325
326
327
328
329 public HColumnDescriptor(final byte [] familyName) {
330 this (familyName == null || familyName.length <= 0?
331 HConstants.EMPTY_BYTE_ARRAY: familyName, DEFAULT_VERSIONS,
332 DEFAULT_COMPRESSION, DEFAULT_IN_MEMORY, DEFAULT_BLOCKCACHE,
333 DEFAULT_TTL, DEFAULT_BLOOMFILTER);
334 }
335
336
337
338
339
340
341
342 public HColumnDescriptor(HColumnDescriptor desc) {
343 super();
344 this.name = desc.name.clone();
345 for (Map.Entry<ImmutableBytesWritable, ImmutableBytesWritable> e:
346 desc.values.entrySet()) {
347 this.values.put(e.getKey(), e.getValue());
348 }
349 for (Map.Entry<String, String> e : desc.configuration.entrySet()) {
350 this.configuration.put(e.getKey(), e.getValue());
351 }
352 setMaxVersions(desc.getMaxVersions());
353 }
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377 @Deprecated
378 public HColumnDescriptor(final byte [] familyName, final int maxVersions,
379 final String compression, final boolean inMemory,
380 final boolean blockCacheEnabled,
381 final int timeToLive, final String bloomFilter) {
382 this(familyName, maxVersions, compression, inMemory, blockCacheEnabled,
383 DEFAULT_BLOCKSIZE, timeToLive, bloomFilter, DEFAULT_REPLICATION_SCOPE);
384 }
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412 @Deprecated
413 public HColumnDescriptor(final byte [] familyName, final int maxVersions,
414 final String compression, final boolean inMemory,
415 final boolean blockCacheEnabled, final int blocksize,
416 final int timeToLive, final String bloomFilter, final int scope) {
417 this(familyName, DEFAULT_MIN_VERSIONS, maxVersions, DEFAULT_KEEP_DELETED,
418 compression, DEFAULT_ENCODE_ON_DISK, DEFAULT_DATA_BLOCK_ENCODING,
419 inMemory, blockCacheEnabled, blocksize, timeToLive, bloomFilter,
420 scope);
421 }
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455 @Deprecated
456 public HColumnDescriptor(final byte[] familyName, final int minVersions,
457 final int maxVersions, final KeepDeletedCells keepDeletedCells,
458 final String compression, final boolean encodeOnDisk,
459 final String dataBlockEncoding, final boolean inMemory,
460 final boolean blockCacheEnabled, final int blocksize,
461 final int timeToLive, final String bloomFilter, final int scope) {
462 isLegalFamilyName(familyName);
463 this.name = familyName;
464
465 if (maxVersions <= 0) {
466
467
468 throw new IllegalArgumentException("Maximum versions must be positive");
469 }
470
471 if (minVersions > 0) {
472 if (timeToLive == HConstants.FOREVER) {
473 throw new IllegalArgumentException("Minimum versions requires TTL.");
474 }
475 if (minVersions >= maxVersions) {
476 throw new IllegalArgumentException("Minimum versions must be < "
477 + "maximum versions.");
478 }
479 }
480
481 setMaxVersions(maxVersions);
482 setMinVersions(minVersions);
483 setKeepDeletedCells(keepDeletedCells);
484 setInMemory(inMemory);
485 setBlockCacheEnabled(blockCacheEnabled);
486 setTimeToLive(timeToLive);
487 setCompressionType(Compression.Algorithm.
488 valueOf(compression.toUpperCase()));
489 setDataBlockEncoding(DataBlockEncoding.
490 valueOf(dataBlockEncoding.toUpperCase()));
491 setBloomFilterType(BloomType.
492 valueOf(bloomFilter.toUpperCase()));
493 setBlocksize(blocksize);
494 setScope(scope);
495 }
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526 @Deprecated
527 public HColumnDescriptor(final byte[] familyName, final int minVersions,
528 final int maxVersions, final boolean keepDeletedCells,
529 final String compression, final boolean encodeOnDisk,
530 final String dataBlockEncoding, final boolean inMemory,
531 final boolean blockCacheEnabled, final int blocksize,
532 final int timeToLive, final String bloomFilter, final int scope) {
533 this(familyName, minVersions, maxVersions,
534 keepDeletedCells ? KeepDeletedCells.TRUE : KeepDeletedCells.FALSE,
535 compression, encodeOnDisk, dataBlockEncoding,
536 inMemory, blockCacheEnabled, blocksize, timeToLive, bloomFilter, scope);
537 }
538
539
540
541
542
543
544
545
546
547 public static byte [] isLegalFamilyName(final byte [] b) {
548 if (b == null) {
549 return b;
550 }
551 Preconditions.checkArgument(b.length != 0, "Family name can not be empty");
552 if (b[0] == '.') {
553 throw new IllegalArgumentException("Family names cannot start with a " +
554 "period: " + Bytes.toString(b));
555 }
556 for (int i = 0; i < b.length; i++) {
557 if (Character.isISOControl(b[i]) || b[i] == ':' || b[i] == '\\' || b[i] == '/') {
558 throw new IllegalArgumentException("Illegal character <" + b[i] +
559 ">. Family names cannot contain control characters or colons: " +
560 Bytes.toString(b));
561 }
562 }
563 byte[] recoveredEdit = Bytes.toBytes(HConstants.RECOVERED_EDITS_DIR);
564 if (Bytes.equals(recoveredEdit, b)) {
565 throw new IllegalArgumentException("Family name cannot be: " +
566 HConstants.RECOVERED_EDITS_DIR);
567 }
568 return b;
569 }
570
571
572
573
574 public byte [] getName() {
575 return name;
576 }
577
578
579
580
581 public String getNameAsString() {
582 return Bytes.toString(this.name);
583 }
584
585
586
587
588
589 public byte[] getValue(byte[] key) {
590 ImmutableBytesWritable ibw = values.get(new ImmutableBytesWritable(key));
591 if (ibw == null)
592 return null;
593 return ibw.get();
594 }
595
596
597
598
599
600 public String getValue(String key) {
601 byte[] value = getValue(Bytes.toBytes(key));
602 if (value == null)
603 return null;
604 return Bytes.toString(value);
605 }
606
607
608
609
610 public Map<ImmutableBytesWritable,ImmutableBytesWritable> getValues() {
611
612 return Collections.unmodifiableMap(values);
613 }
614
615
616
617
618
619
620 public HColumnDescriptor setValue(byte[] key, byte[] value) {
621 if (Bytes.compareTo(Bytes.toBytes(HConstants.VERSIONS), key) == 0) {
622 cachedMaxVersions = UNINITIALIZED;
623 }
624 values.put(new ImmutableBytesWritable(key),
625 new ImmutableBytesWritable(value));
626 return this;
627 }
628
629
630
631
632 public void remove(final byte [] key) {
633 values.remove(new ImmutableBytesWritable(key));
634 }
635
636
637
638
639
640
641 public HColumnDescriptor setValue(String key, String value) {
642 if (value == null) {
643 remove(Bytes.toBytes(key));
644 } else {
645 setValue(Bytes.toBytes(key), Bytes.toBytes(value));
646 }
647 return this;
648 }
649
650
651 public Compression.Algorithm getCompression() {
652 String n = getValue(COMPRESSION);
653 if (n == null) {
654 return Compression.Algorithm.NONE;
655 }
656 return Compression.Algorithm.valueOf(n.toUpperCase());
657 }
658
659
660
661 public Compression.Algorithm getCompactionCompression() {
662 String n = getValue(COMPRESSION_COMPACT);
663 if (n == null) {
664 return getCompression();
665 }
666 return Compression.Algorithm.valueOf(n.toUpperCase());
667 }
668
669
670 public int getMaxVersions() {
671 if (this.cachedMaxVersions == UNINITIALIZED) {
672 String v = getValue(HConstants.VERSIONS);
673 this.cachedMaxVersions = Integer.parseInt(v);
674 }
675 return this.cachedMaxVersions;
676 }
677
678
679
680
681
682 public HColumnDescriptor setMaxVersions(int maxVersions) {
683 if (maxVersions <= 0) {
684
685
686 throw new IllegalArgumentException("Maximum versions must be positive");
687 }
688 if (maxVersions < this.getMinVersions()) {
689 throw new IllegalArgumentException("Set MaxVersion to " + maxVersions
690 + " while minVersion is " + this.getMinVersions()
691 + ". Maximum versions must be >= minimum versions ");
692 }
693 setValue(HConstants.VERSIONS, Integer.toString(maxVersions));
694 cachedMaxVersions = maxVersions;
695 return this;
696 }
697
698
699
700
701
702
703
704
705 public HColumnDescriptor setVersions(int minVersions, int maxVersions) {
706 if (minVersions <= 0) {
707
708
709 throw new IllegalArgumentException("Minimum versions must be positive");
710 }
711
712 if (maxVersions < minVersions) {
713 throw new IllegalArgumentException("Unable to set MaxVersion to " + maxVersions
714 + " and set MinVersion to " + minVersions
715 + ", as maximum versions must be >= minimum versions.");
716 }
717 setMinVersions(minVersions);
718 setMaxVersions(maxVersions);
719 return this;
720 }
721
722
723
724
725 public synchronized int getBlocksize() {
726 if (this.blocksize == null) {
727 String value = getValue(BLOCKSIZE);
728 this.blocksize = (value != null)?
729 Integer.decode(value): Integer.valueOf(DEFAULT_BLOCKSIZE);
730 }
731 return this.blocksize.intValue();
732 }
733
734
735
736
737
738
739 public HColumnDescriptor setBlocksize(int s) {
740 setValue(BLOCKSIZE, Integer.toString(s));
741 this.blocksize = null;
742 return this;
743 }
744
745
746
747
748 public Compression.Algorithm getCompressionType() {
749 return getCompression();
750 }
751
752
753
754
755
756
757
758
759
760 public HColumnDescriptor setCompressionType(Compression.Algorithm type) {
761 return setValue(COMPRESSION, type.getName().toUpperCase());
762 }
763
764
765
766
767
768
769
770 @Deprecated
771 public DataBlockEncoding getDataBlockEncodingOnDisk() {
772 return getDataBlockEncoding();
773 }
774
775
776
777
778
779
780
781
782
783 @Deprecated
784 public HColumnDescriptor setEncodeOnDisk(boolean encodeOnDisk) {
785 return this;
786 }
787
788
789
790
791
792 public DataBlockEncoding getDataBlockEncoding() {
793 String type = getValue(DATA_BLOCK_ENCODING);
794 if (type == null) {
795 type = DEFAULT_DATA_BLOCK_ENCODING;
796 }
797 return DataBlockEncoding.valueOf(type);
798 }
799
800
801
802
803
804
805 public HColumnDescriptor setDataBlockEncoding(DataBlockEncoding type) {
806 String name;
807 if (type != null) {
808 name = type.toString();
809 } else {
810 name = DataBlockEncoding.NONE.toString();
811 }
812 return setValue(DATA_BLOCK_ENCODING, name);
813 }
814
815
816
817
818
819
820
821
822 public HColumnDescriptor setCompressTags(boolean compressTags) {
823 return setValue(COMPRESS_TAGS, String.valueOf(compressTags));
824 }
825
826
827
828
829
830
831
832
833 @Deprecated
834 public boolean shouldCompressTags() {
835 String compressTagsStr = getValue(COMPRESS_TAGS);
836 boolean compressTags = DEFAULT_COMPRESS_TAGS;
837 if (compressTagsStr != null) {
838 compressTags = Boolean.valueOf(compressTagsStr);
839 }
840 return compressTags;
841 }
842
843
844
845
846
847 public boolean isCompressTags() {
848 String compressTagsStr = getValue(COMPRESS_TAGS);
849 boolean compressTags = DEFAULT_COMPRESS_TAGS;
850 if (compressTagsStr != null) {
851 compressTags = Boolean.valueOf(compressTagsStr);
852 }
853 return compressTags;
854 }
855
856
857
858
859 public Compression.Algorithm getCompactionCompressionType() {
860 return getCompactionCompression();
861 }
862
863
864
865
866
867
868
869
870
871 public HColumnDescriptor setCompactionCompressionType(
872 Compression.Algorithm type) {
873 return setValue(COMPRESSION_COMPACT, type.getName().toUpperCase());
874 }
875
876
877
878
879
880 public boolean isInMemory() {
881 String value = getValue(HConstants.IN_MEMORY);
882 if (value != null)
883 return Boolean.valueOf(value).booleanValue();
884 return DEFAULT_IN_MEMORY;
885 }
886
887
888
889
890
891
892 public HColumnDescriptor setInMemory(boolean inMemory) {
893 return setValue(HConstants.IN_MEMORY, Boolean.toString(inMemory));
894 }
895
896
897
898
899
900
901 public KeepDeletedCells getKeepDeletedCellsAsEnum() {
902 String value = getValue(KEEP_DELETED_CELLS);
903 if (value != null) {
904
905 return KeepDeletedCells.valueOf(value.toUpperCase());
906 }
907 return DEFAULT_KEEP_DELETED;
908 }
909
910
911
912
913
914
915
916 @Deprecated
917 public boolean getKeepDeletedCells() {
918 String value = getValue(KEEP_DELETED_CELLS);
919 if (value != null) {
920 KeepDeletedCells kdc = KeepDeletedCells.valueOf(value);
921 switch (kdc) {
922 case TRUE:
923 case TTL:
924 return true;
925 case FALSE:
926 return false;
927 default:
928 throw new IllegalStateException("The value " + kdc + " is not a valid code");
929 }
930 }
931 return Boolean.valueOf(DEFAULT_KEEP_DELETED.toString());
932 }
933
934
935
936
937
938
939
940
941
942
943 @Deprecated
944 public HColumnDescriptor setKeepDeletedCells(boolean keepDeletedCells) {
945 return setValue(KEEP_DELETED_CELLS, (keepDeletedCells ? KeepDeletedCells.TRUE
946 : KeepDeletedCells.FALSE).toString());
947 }
948
949
950
951
952
953
954 public HColumnDescriptor setKeepDeletedCells(KeepDeletedCells keepDeletedCells) {
955 return setValue(KEEP_DELETED_CELLS, keepDeletedCells.toString());
956 }
957
958
959
960
961 public int getTimeToLive() {
962 String value = getValue(TTL);
963 return (value != null)? Integer.parseInt(value): DEFAULT_TTL;
964 }
965
966
967
968
969
970 public HColumnDescriptor setTimeToLive(int timeToLive) {
971 return setValue(TTL, Integer.toString(timeToLive));
972 }
973
974
975
976
977 public int getMinVersions() {
978 String value = getValue(MIN_VERSIONS);
979 return (value != null)? Integer.parseInt(value): 0;
980 }
981
982
983
984
985
986
987 public HColumnDescriptor setMinVersions(int minVersions) {
988 return setValue(MIN_VERSIONS, Integer.toString(minVersions));
989 }
990
991
992
993
994
995 public boolean isBlockCacheEnabled() {
996 String value = getValue(BLOCKCACHE);
997 if (value != null)
998 return Boolean.parseBoolean(value);
999 return DEFAULT_BLOCKCACHE;
1000 }
1001
1002
1003
1004
1005
1006
1007 public HColumnDescriptor setBlockCacheEnabled(boolean blockCacheEnabled) {
1008 return setValue(BLOCKCACHE, Boolean.toString(blockCacheEnabled));
1009 }
1010
1011
1012
1013
1014 public BloomType getBloomFilterType() {
1015 String n = getValue(BLOOMFILTER);
1016 if (n == null) {
1017 n = DEFAULT_BLOOMFILTER;
1018 }
1019 return BloomType.valueOf(n.toUpperCase());
1020 }
1021
1022
1023
1024
1025
1026 public HColumnDescriptor setBloomFilterType(final BloomType bt) {
1027 return setValue(BLOOMFILTER, bt.toString());
1028 }
1029
1030
1031
1032
1033 public int getScope() {
1034 byte[] value = getValue(REPLICATION_SCOPE_BYTES);
1035 if (value != null) {
1036 return Integer.parseInt(Bytes.toString(value));
1037 }
1038 return DEFAULT_REPLICATION_SCOPE;
1039 }
1040
1041
1042
1043
1044
1045 public HColumnDescriptor setScope(int scope) {
1046 return setValue(REPLICATION_SCOPE, Integer.toString(scope));
1047 }
1048
1049
1050
1051
1052
1053
1054
1055 @Deprecated
1056 public boolean shouldCacheDataOnWrite() {
1057 return setAndGetBoolean(CACHE_DATA_ON_WRITE, DEFAULT_CACHE_DATA_ON_WRITE);
1058 }
1059
1060
1061
1062
1063 public boolean isCacheDataOnWrite() {
1064 return setAndGetBoolean(CACHE_DATA_ON_WRITE, DEFAULT_CACHE_DATA_ON_WRITE);
1065 }
1066
1067
1068
1069
1070
1071 public HColumnDescriptor setCacheDataOnWrite(boolean value) {
1072 return setValue(CACHE_DATA_ON_WRITE, Boolean.toString(value));
1073 }
1074
1075
1076
1077
1078
1079
1080
1081
1082 @Deprecated
1083 public boolean shouldCacheDataInL1() {
1084 return setAndGetBoolean(CACHE_DATA_IN_L1, DEFAULT_CACHE_DATA_IN_L1);
1085 }
1086
1087
1088
1089
1090
1091 public boolean isCacheDataInL1() {
1092 return setAndGetBoolean(CACHE_DATA_IN_L1, DEFAULT_CACHE_DATA_IN_L1);
1093 }
1094
1095
1096
1097
1098
1099
1100 public HColumnDescriptor setCacheDataInL1(boolean value) {
1101 return setValue(CACHE_DATA_IN_L1, Boolean.toString(value));
1102 }
1103
1104 private boolean setAndGetBoolean(final String key, final boolean defaultSetting) {
1105 String value = getValue(key);
1106 if (value != null) return Boolean.parseBoolean(value);
1107 return defaultSetting;
1108 }
1109
1110
1111
1112
1113
1114
1115
1116
1117 @Deprecated
1118 public boolean shouldCacheIndexesOnWrite() {
1119 return setAndGetBoolean(CACHE_INDEX_ON_WRITE, DEFAULT_CACHE_INDEX_ON_WRITE);
1120 }
1121
1122
1123
1124
1125 public boolean isCacheIndexesOnWrite() {
1126 return setAndGetBoolean(CACHE_INDEX_ON_WRITE, DEFAULT_CACHE_INDEX_ON_WRITE);
1127 }
1128
1129
1130
1131
1132
1133 public HColumnDescriptor setCacheIndexesOnWrite(boolean value) {
1134 return setValue(CACHE_INDEX_ON_WRITE, Boolean.toString(value));
1135 }
1136
1137
1138
1139
1140
1141
1142
1143
1144 @Deprecated
1145 public boolean shouldCacheBloomsOnWrite() {
1146 return setAndGetBoolean(CACHE_BLOOMS_ON_WRITE, DEFAULT_CACHE_BLOOMS_ON_WRITE);
1147 }
1148
1149
1150
1151
1152 public boolean isCacheBloomsOnWrite() {
1153 return setAndGetBoolean(CACHE_BLOOMS_ON_WRITE, DEFAULT_CACHE_BLOOMS_ON_WRITE);
1154 }
1155
1156
1157
1158
1159
1160 public HColumnDescriptor setCacheBloomsOnWrite(boolean value) {
1161 return setValue(CACHE_BLOOMS_ON_WRITE, Boolean.toString(value));
1162 }
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172 @Deprecated
1173 public boolean shouldEvictBlocksOnClose() {
1174 return setAndGetBoolean(EVICT_BLOCKS_ON_CLOSE, DEFAULT_EVICT_BLOCKS_ON_CLOSE);
1175 }
1176
1177
1178
1179
1180 public boolean isEvictBlocksOnClose() {
1181 return setAndGetBoolean(EVICT_BLOCKS_ON_CLOSE, DEFAULT_EVICT_BLOCKS_ON_CLOSE);
1182 }
1183
1184
1185
1186
1187
1188
1189 public HColumnDescriptor setEvictBlocksOnClose(boolean value) {
1190 return setValue(EVICT_BLOCKS_ON_CLOSE, Boolean.toString(value));
1191 }
1192
1193
1194
1195
1196
1197
1198
1199
1200 @Deprecated
1201 public boolean shouldPrefetchBlocksOnOpen() {
1202 return setAndGetBoolean(PREFETCH_BLOCKS_ON_OPEN, DEFAULT_PREFETCH_BLOCKS_ON_OPEN);
1203 }
1204
1205
1206
1207
1208 public boolean isPrefetchBlocksOnOpen() {
1209 return setAndGetBoolean(PREFETCH_BLOCKS_ON_OPEN, DEFAULT_PREFETCH_BLOCKS_ON_OPEN);
1210 }
1211
1212
1213
1214
1215
1216 public HColumnDescriptor setPrefetchBlocksOnOpen(boolean value) {
1217 return setValue(PREFETCH_BLOCKS_ON_OPEN, Boolean.toString(value));
1218 }
1219
1220
1221
1222
1223 @Override
1224 public String toString() {
1225 StringBuilder s = new StringBuilder();
1226
1227 s.append('{');
1228 s.append(HConstants.NAME);
1229 s.append(" => '");
1230 s.append(Bytes.toString(name));
1231 s.append("'");
1232 s.append(getValues(true));
1233 s.append('}');
1234 return s.toString();
1235 }
1236
1237
1238
1239
1240 public String toStringCustomizedValues() {
1241 StringBuilder s = new StringBuilder();
1242 s.append('{');
1243 s.append(HConstants.NAME);
1244 s.append(" => '");
1245 s.append(Bytes.toString(name));
1246 s.append("'");
1247 s.append(getValues(false));
1248 s.append('}');
1249 return s.toString();
1250 }
1251
1252 private StringBuilder getValues(boolean printDefaults) {
1253 StringBuilder s = new StringBuilder();
1254
1255 boolean hasConfigKeys = false;
1256
1257
1258 for (ImmutableBytesWritable k : values.keySet()) {
1259 if (!RESERVED_KEYWORDS.contains(k)) {
1260 hasConfigKeys = true;
1261 continue;
1262 }
1263 String key = Bytes.toString(k.get());
1264 String value = Bytes.toStringBinary(values.get(k).get());
1265 if (printDefaults
1266 || !DEFAULT_VALUES.containsKey(key)
1267 || !DEFAULT_VALUES.get(key).equalsIgnoreCase(value)) {
1268 s.append(", ");
1269 s.append(key);
1270 s.append(" => ");
1271 s.append('\'').append(PrettyPrinter.format(value, getUnit(key))).append('\'');
1272 }
1273 }
1274
1275
1276 if (hasConfigKeys) {
1277 s.append(", ");
1278 s.append(HConstants.METADATA).append(" => ");
1279 s.append('{');
1280 boolean printComma = false;
1281 for (ImmutableBytesWritable k : values.keySet()) {
1282 if (RESERVED_KEYWORDS.contains(k)) {
1283 continue;
1284 }
1285 String key = Bytes.toString(k.get());
1286 String value = Bytes.toStringBinary(values.get(k).get());
1287 if (printComma) {
1288 s.append(", ");
1289 }
1290 printComma = true;
1291 s.append('\'').append(key).append('\'');
1292 s.append(" => ");
1293 s.append('\'').append(PrettyPrinter.format(value, getUnit(key))).append('\'');
1294 }
1295 s.append('}');
1296 }
1297
1298 if (!configuration.isEmpty()) {
1299 s.append(", ");
1300 s.append(HConstants.CONFIGURATION).append(" => ");
1301 s.append('{');
1302 boolean printCommaForConfiguration = false;
1303 for (Map.Entry<String, String> e : configuration.entrySet()) {
1304 if (printCommaForConfiguration) s.append(", ");
1305 printCommaForConfiguration = true;
1306 s.append('\'').append(e.getKey()).append('\'');
1307 s.append(" => ");
1308 s.append('\'').append(PrettyPrinter.format(e.getValue(), getUnit(e.getKey()))).append('\'');
1309 }
1310 s.append("}");
1311 }
1312 return s;
1313 }
1314
1315 public static Unit getUnit(String key) {
1316 Unit unit;
1317
1318 if (key.equals(HColumnDescriptor.TTL)) {
1319 unit = Unit.TIME_INTERVAL;
1320 } else if (key.equals(HColumnDescriptor.MOB_THRESHOLD)) {
1321 unit = Unit.LONG;
1322 } else if (key.equals(HColumnDescriptor.IS_MOB)) {
1323 unit = Unit.BOOLEAN;
1324 } else {
1325 unit = Unit.NONE;
1326 }
1327 return unit;
1328 }
1329
1330 public static Map<String, String> getDefaultValues() {
1331 return Collections.unmodifiableMap(DEFAULT_VALUES);
1332 }
1333
1334
1335
1336
1337 @Override
1338 public boolean equals(Object obj) {
1339 if (this == obj) {
1340 return true;
1341 }
1342 if (obj == null) {
1343 return false;
1344 }
1345 if (!(obj instanceof HColumnDescriptor)) {
1346 return false;
1347 }
1348 return compareTo((HColumnDescriptor)obj) == 0;
1349 }
1350
1351
1352
1353
1354 @Override
1355 public int hashCode() {
1356 int result = Bytes.hashCode(this.name);
1357 result ^= Byte.valueOf(COLUMN_DESCRIPTOR_VERSION).hashCode();
1358 result ^= values.hashCode();
1359 result ^= configuration.hashCode();
1360 return result;
1361 }
1362
1363
1364
1365
1366 @Deprecated
1367 public void readFields(DataInput in) throws IOException {
1368 int version = in.readByte();
1369 if (version < 6) {
1370 if (version <= 2) {
1371 Text t = new Text();
1372 t.readFields(in);
1373 this.name = t.getBytes();
1374
1375
1376
1377
1378 } else {
1379 this.name = Bytes.readByteArray(in);
1380 }
1381 this.values.clear();
1382 setMaxVersions(in.readInt());
1383 int ordinal = in.readInt();
1384 setCompressionType(Compression.Algorithm.values()[ordinal]);
1385 setInMemory(in.readBoolean());
1386 setBloomFilterType(in.readBoolean() ? BloomType.ROW : BloomType.NONE);
1387 if (getBloomFilterType() != BloomType.NONE && version < 5) {
1388
1389
1390
1391
1392 throw new UnsupportedClassVersionError(this.getClass().getName() +
1393 " does not support backward compatibility with versions older " +
1394 "than version 5");
1395 }
1396 if (version > 1) {
1397 setBlockCacheEnabled(in.readBoolean());
1398 }
1399 if (version > 2) {
1400 setTimeToLive(in.readInt());
1401 }
1402 } else {
1403
1404 this.name = Bytes.readByteArray(in);
1405 this.values.clear();
1406 int numValues = in.readInt();
1407 for (int i = 0; i < numValues; i++) {
1408 ImmutableBytesWritable key = new ImmutableBytesWritable();
1409 ImmutableBytesWritable value = new ImmutableBytesWritable();
1410 key.readFields(in);
1411 value.readFields(in);
1412
1413
1414 if (version < 8 && Bytes.toString(key.get()).equals(BLOOMFILTER)) {
1415 value.set(Bytes.toBytes(
1416 Boolean.getBoolean(Bytes.toString(value.get()))
1417 ? BloomType.ROW.toString()
1418 : BloomType.NONE.toString()));
1419 }
1420
1421 values.put(key, value);
1422 }
1423 if (version == 6) {
1424
1425 setValue(COMPRESSION, Compression.Algorithm.NONE.getName());
1426 }
1427 String value = getValue(HConstants.VERSIONS);
1428 this.cachedMaxVersions = (value != null)?
1429 Integer.parseInt(value): DEFAULT_VERSIONS;
1430 if (version > 10) {
1431 configuration.clear();
1432 int numConfigs = in.readInt();
1433 for (int i = 0; i < numConfigs; i++) {
1434 ImmutableBytesWritable key = new ImmutableBytesWritable();
1435 ImmutableBytesWritable val = new ImmutableBytesWritable();
1436 key.readFields(in);
1437 val.readFields(in);
1438 configuration.put(
1439 Bytes.toString(key.get(), key.getOffset(), key.getLength()),
1440 Bytes.toString(val.get(), val.getOffset(), val.getLength()));
1441 }
1442 }
1443 }
1444 }
1445
1446
1447
1448
1449 @Deprecated
1450 public void write(DataOutput out) throws IOException {
1451 out.writeByte(COLUMN_DESCRIPTOR_VERSION);
1452 Bytes.writeByteArray(out, this.name);
1453 out.writeInt(values.size());
1454 for (Map.Entry<ImmutableBytesWritable, ImmutableBytesWritable> e:
1455 values.entrySet()) {
1456 e.getKey().write(out);
1457 e.getValue().write(out);
1458 }
1459 out.writeInt(configuration.size());
1460 for (Map.Entry<String, String> e : configuration.entrySet()) {
1461 new ImmutableBytesWritable(Bytes.toBytes(e.getKey())).write(out);
1462 new ImmutableBytesWritable(Bytes.toBytes(e.getValue())).write(out);
1463 }
1464 }
1465
1466
1467 @Override
1468 public int compareTo(HColumnDescriptor o) {
1469 int result = Bytes.compareTo(this.name, o.getName());
1470 if (result == 0) {
1471
1472 result = this.values.hashCode() - o.values.hashCode();
1473 if (result < 0)
1474 result = -1;
1475 else if (result > 0)
1476 result = 1;
1477 }
1478 if (result == 0) {
1479 result = this.configuration.hashCode() - o.configuration.hashCode();
1480 if (result < 0)
1481 result = -1;
1482 else if (result > 0)
1483 result = 1;
1484 }
1485 return result;
1486 }
1487
1488
1489
1490
1491
1492 public byte [] toByteArray() {
1493 return ProtobufUtil.prependPBMagic(convert().toByteArray());
1494 }
1495
1496
1497
1498
1499
1500
1501
1502 public static HColumnDescriptor parseFrom(final byte [] bytes) throws DeserializationException {
1503 if (!ProtobufUtil.isPBMagicPrefix(bytes)) throw new DeserializationException("No magic");
1504 int pblen = ProtobufUtil.lengthOfPBMagic();
1505 ColumnFamilySchema.Builder builder = ColumnFamilySchema.newBuilder();
1506 ColumnFamilySchema cfs = null;
1507 try {
1508 ProtobufUtil.mergeFrom(builder, bytes, pblen, bytes.length - pblen);
1509 cfs = builder.build();
1510 } catch (IOException e) {
1511 throw new DeserializationException(e);
1512 }
1513 return convert(cfs);
1514 }
1515
1516
1517
1518
1519
1520 public static HColumnDescriptor convert(final ColumnFamilySchema cfs) {
1521
1522
1523
1524 HColumnDescriptor hcd = new HColumnDescriptor();
1525 hcd.name = cfs.getName().toByteArray();
1526 for (BytesBytesPair a: cfs.getAttributesList()) {
1527 hcd.setValue(a.getFirst().toByteArray(), a.getSecond().toByteArray());
1528 }
1529 for (NameStringPair a: cfs.getConfigurationList()) {
1530 hcd.setConfiguration(a.getName(), a.getValue());
1531 }
1532 return hcd;
1533 }
1534
1535
1536
1537
1538 public ColumnFamilySchema convert() {
1539 ColumnFamilySchema.Builder builder = ColumnFamilySchema.newBuilder();
1540 builder.setName(ByteStringer.wrap(getName()));
1541 for (Map.Entry<ImmutableBytesWritable, ImmutableBytesWritable> e: this.values.entrySet()) {
1542 BytesBytesPair.Builder aBuilder = BytesBytesPair.newBuilder();
1543 aBuilder.setFirst(ByteStringer.wrap(e.getKey().get()));
1544 aBuilder.setSecond(ByteStringer.wrap(e.getValue().get()));
1545 builder.addAttributes(aBuilder.build());
1546 }
1547 for (Map.Entry<String, String> e : this.configuration.entrySet()) {
1548 NameStringPair.Builder aBuilder = NameStringPair.newBuilder();
1549 aBuilder.setName(e.getKey());
1550 aBuilder.setValue(e.getValue());
1551 builder.addConfiguration(aBuilder.build());
1552 }
1553 return builder.build();
1554 }
1555
1556
1557
1558
1559 public String getConfigurationValue(String key) {
1560 return configuration.get(key);
1561 }
1562
1563
1564
1565
1566 public Map<String, String> getConfiguration() {
1567
1568 return Collections.unmodifiableMap(configuration);
1569 }
1570
1571
1572
1573
1574
1575
1576 public void setConfiguration(String key, String value) {
1577 if (value == null) {
1578 removeConfiguration(key);
1579 } else {
1580 configuration.put(key, value);
1581 }
1582 }
1583
1584
1585
1586
1587 public void removeConfiguration(final String key) {
1588 configuration.remove(key);
1589 }
1590
1591
1592
1593
1594 public String getEncryptionType() {
1595 return getValue(ENCRYPTION);
1596 }
1597
1598
1599
1600
1601
1602 public HColumnDescriptor setEncryptionType(String algorithm) {
1603 setValue(ENCRYPTION, algorithm);
1604 return this;
1605 }
1606
1607
1608 public byte[] getEncryptionKey() {
1609 return getValue(Bytes.toBytes(ENCRYPTION_KEY));
1610 }
1611
1612
1613 public HColumnDescriptor setEncryptionKey(byte[] keyBytes) {
1614 setValue(Bytes.toBytes(ENCRYPTION_KEY), keyBytes);
1615 return this;
1616 }
1617
1618
1619
1620
1621
1622
1623
1624 public long getMobThreshold() {
1625 byte[] threshold = getValue(MOB_THRESHOLD_BYTES);
1626 return threshold != null && threshold.length == Bytes.SIZEOF_LONG ? Bytes.toLong(threshold)
1627 : DEFAULT_MOB_THRESHOLD;
1628 }
1629
1630
1631
1632
1633
1634
1635 public HColumnDescriptor setMobThreshold(long threshold) {
1636 setValue(MOB_THRESHOLD_BYTES, Bytes.toBytes(threshold));
1637 return this;
1638 }
1639
1640
1641
1642
1643
1644 public boolean isMobEnabled() {
1645 byte[] isMobEnabled = getValue(IS_MOB_BYTES);
1646 return isMobEnabled != null && isMobEnabled.length == Bytes.SIZEOF_BOOLEAN
1647 && Bytes.toBoolean(isMobEnabled);
1648 }
1649
1650
1651
1652
1653
1654
1655 public HColumnDescriptor setMobEnabled(boolean isMobEnabled) {
1656 setValue(IS_MOB_BYTES, Bytes.toBytes(isMobEnabled));
1657 return this;
1658 }
1659
1660
1661
1662
1663
1664
1665
1666
1667 public short getDFSReplication() {
1668 String rf = getValue(DFS_REPLICATION);
1669 return rf == null ? DEFAULT_DFS_REPLICATION : Short.parseShort(rf);
1670 }
1671
1672
1673
1674
1675
1676
1677
1678
1679 public HColumnDescriptor setDFSReplication(short replication) {
1680 if (replication < 1 && replication != DEFAULT_DFS_REPLICATION) {
1681 throw new IllegalArgumentException(
1682 "DFS replication factor cannot be less than 1 if explictly set.");
1683 }
1684 setValue(DFS_REPLICATION, Short.toString(replication));
1685 return this;
1686 }
1687 }