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