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