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