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