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