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