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