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