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