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