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