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.ArrayList;
25 import java.util.Collection;
26 import java.util.Collections;
27 import java.util.HashMap;
28 import java.util.HashSet;
29 import java.util.Iterator;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.Set;
33 import java.util.TreeMap;
34 import java.util.TreeSet;
35 import java.util.regex.Matcher;
36
37 import org.apache.hadoop.hbase.util.ByteStringer;
38 import org.apache.commons.logging.Log;
39 import org.apache.commons.logging.LogFactory;
40 import org.apache.hadoop.hbase.classification.InterfaceAudience;
41 import org.apache.hadoop.hbase.classification.InterfaceStability;
42 import org.apache.hadoop.conf.Configuration;
43 import org.apache.hadoop.fs.Path;
44 import org.apache.hadoop.hbase.client.Durability;
45 import org.apache.hadoop.hbase.client.RegionReplicaUtil;
46 import org.apache.hadoop.hbase.exceptions.DeserializationException;
47 import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
48 import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
49 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.BytesBytesPair;
50 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.ColumnFamilySchema;
51 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.NameStringPair;
52 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableSchema;
53 import org.apache.hadoop.hbase.regionserver.BloomType;
54 import org.apache.hadoop.hbase.security.User;
55 import org.apache.hadoop.hbase.util.Bytes;
56 import org.apache.hadoop.hbase.util.Writables;
57 import org.apache.hadoop.io.WritableComparable;
58
59
60
61
62
63
64
65 @InterfaceAudience.Public
66 @InterfaceStability.Evolving
67 public class HTableDescriptor implements WritableComparable<HTableDescriptor> {
68
69 private static final Log LOG = LogFactory.getLog(HTableDescriptor.class);
70
71
72
73
74
75
76
77
78
79 private static final byte TABLE_DESCRIPTOR_VERSION = 7;
80
81 private TableName name = null;
82
83
84
85
86
87
88 private final Map<ImmutableBytesWritable, ImmutableBytesWritable> values =
89 new HashMap<ImmutableBytesWritable, ImmutableBytesWritable>();
90
91
92
93
94
95
96 private final Map<String, String> configuration = new HashMap<String, String>();
97
98 public static final String SPLIT_POLICY = "SPLIT_POLICY";
99
100
101
102
103
104
105
106
107 public static final String MAX_FILESIZE = "MAX_FILESIZE";
108 private static final ImmutableBytesWritable MAX_FILESIZE_KEY =
109 new ImmutableBytesWritable(Bytes.toBytes(MAX_FILESIZE));
110
111 public static final String OWNER = "OWNER";
112 public static final ImmutableBytesWritable OWNER_KEY =
113 new ImmutableBytesWritable(Bytes.toBytes(OWNER));
114
115
116
117
118
119
120
121 public static final String READONLY = "READONLY";
122 private static final ImmutableBytesWritable READONLY_KEY =
123 new ImmutableBytesWritable(Bytes.toBytes(READONLY));
124
125
126
127
128
129
130
131 public static final String COMPACTION_ENABLED = "COMPACTION_ENABLED";
132 private static final ImmutableBytesWritable COMPACTION_ENABLED_KEY =
133 new ImmutableBytesWritable(Bytes.toBytes(COMPACTION_ENABLED));
134
135
136
137
138
139
140
141
142 public static final String MEMSTORE_FLUSHSIZE = "MEMSTORE_FLUSHSIZE";
143 private static final ImmutableBytesWritable MEMSTORE_FLUSHSIZE_KEY =
144 new ImmutableBytesWritable(Bytes.toBytes(MEMSTORE_FLUSHSIZE));
145
146 public static final String FLUSH_POLICY = "FLUSH_POLICY";
147
148
149
150
151
152
153
154 public static final String IS_ROOT = "IS_ROOT";
155 private static final ImmutableBytesWritable IS_ROOT_KEY =
156 new ImmutableBytesWritable(Bytes.toBytes(IS_ROOT));
157
158
159
160
161
162
163
164
165 public static final String IS_META = "IS_META";
166 private static final ImmutableBytesWritable IS_META_KEY =
167 new ImmutableBytesWritable(Bytes.toBytes(IS_META));
168
169
170
171
172
173
174 @Deprecated
175 public static final String DEFERRED_LOG_FLUSH = "DEFERRED_LOG_FLUSH";
176 @Deprecated
177 private static final ImmutableBytesWritable DEFERRED_LOG_FLUSH_KEY =
178 new ImmutableBytesWritable(Bytes.toBytes(DEFERRED_LOG_FLUSH));
179
180
181
182
183 public static final String DURABILITY = "DURABILITY";
184 private static final ImmutableBytesWritable DURABILITY_KEY =
185 new ImmutableBytesWritable(Bytes.toBytes("DURABILITY"));
186
187
188
189
190 public static final String REGION_REPLICATION = "REGION_REPLICATION";
191 private static final ImmutableBytesWritable REGION_REPLICATION_KEY =
192 new ImmutableBytesWritable(Bytes.toBytes(REGION_REPLICATION));
193
194
195
196
197
198 public static final String REGION_MEMSTORE_REPLICATION = "REGION_MEMSTORE_REPLICATION";
199 private static final ImmutableBytesWritable REGION_MEMSTORE_REPLICATION_KEY =
200 new ImmutableBytesWritable(Bytes.toBytes(REGION_MEMSTORE_REPLICATION));
201
202
203
204
205
206
207
208 public static final String NORMALIZATION_ENABLED = "NORMALIZATION_ENABLED";
209 private static final ImmutableBytesWritable NORMALIZATION_ENABLED_KEY =
210 new ImmutableBytesWritable(Bytes.toBytes(NORMALIZATION_ENABLED));
211
212
213 private static final Durability DEFAULT_DURABLITY = Durability.USE_DEFAULT;
214
215
216
217
218
219
220 private static final ImmutableBytesWritable FALSE =
221 new ImmutableBytesWritable(Bytes.toBytes(Boolean.FALSE.toString()));
222
223 private static final ImmutableBytesWritable TRUE =
224 new ImmutableBytesWritable(Bytes.toBytes(Boolean.TRUE.toString()));
225
226 private static final boolean DEFAULT_DEFERRED_LOG_FLUSH = false;
227
228
229
230
231 public static final boolean DEFAULT_READONLY = false;
232
233
234
235
236 public static final boolean DEFAULT_COMPACTION_ENABLED = true;
237
238
239
240
241 public static final boolean DEFAULT_NORMALIZATION_ENABLED = false;
242
243
244
245
246
247 public static final long DEFAULT_MEMSTORE_FLUSH_SIZE = 1024*1024*128L;
248
249 public static final int DEFAULT_REGION_REPLICATION = 1;
250
251 public static final boolean DEFAULT_REGION_MEMSTORE_REPLICATION = true;
252
253 private final static Map<String, String> DEFAULT_VALUES
254 = new HashMap<String, String>();
255 private final static Set<ImmutableBytesWritable> RESERVED_KEYWORDS
256 = new HashSet<ImmutableBytesWritable>();
257 static {
258 DEFAULT_VALUES.put(MAX_FILESIZE,
259 String.valueOf(HConstants.DEFAULT_MAX_FILE_SIZE));
260 DEFAULT_VALUES.put(READONLY, String.valueOf(DEFAULT_READONLY));
261 DEFAULT_VALUES.put(MEMSTORE_FLUSHSIZE,
262 String.valueOf(DEFAULT_MEMSTORE_FLUSH_SIZE));
263 DEFAULT_VALUES.put(DEFERRED_LOG_FLUSH,
264 String.valueOf(DEFAULT_DEFERRED_LOG_FLUSH));
265 DEFAULT_VALUES.put(DURABILITY, DEFAULT_DURABLITY.name());
266 DEFAULT_VALUES.put(REGION_REPLICATION, String.valueOf(DEFAULT_REGION_REPLICATION));
267 DEFAULT_VALUES.put(NORMALIZATION_ENABLED, String.valueOf(DEFAULT_NORMALIZATION_ENABLED));
268 for (String s : DEFAULT_VALUES.keySet()) {
269 RESERVED_KEYWORDS.add(new ImmutableBytesWritable(Bytes.toBytes(s)));
270 }
271 RESERVED_KEYWORDS.add(IS_ROOT_KEY);
272 RESERVED_KEYWORDS.add(IS_META_KEY);
273 }
274
275
276
277
278 private volatile Boolean meta = null;
279
280
281
282 private volatile Boolean root = null;
283
284
285
286
287 private Durability durability = null;
288
289
290
291
292 private final Map<byte [], HColumnDescriptor> families =
293 new TreeMap<byte [], HColumnDescriptor>(Bytes.BYTES_RAWCOMPARATOR);
294
295
296
297
298
299 @InterfaceAudience.Private
300 protected HTableDescriptor(final TableName name, HColumnDescriptor[] families) {
301 setName(name);
302 for(HColumnDescriptor descriptor : families) {
303 this.families.put(descriptor.getName(), descriptor);
304 }
305 }
306
307
308
309
310
311 protected HTableDescriptor(final TableName name, HColumnDescriptor[] families,
312 Map<ImmutableBytesWritable,ImmutableBytesWritable> values) {
313 setName(name);
314 for(HColumnDescriptor descriptor : families) {
315 this.families.put(descriptor.getName(), descriptor);
316 }
317 for (Map.Entry<ImmutableBytesWritable, ImmutableBytesWritable> entry:
318 values.entrySet()) {
319 setValue(entry.getKey(), entry.getValue());
320 }
321 }
322
323
324
325
326
327
328
329
330
331 @Deprecated
332 public HTableDescriptor() {
333 super();
334 }
335
336
337
338
339
340
341 public HTableDescriptor(final TableName name) {
342 super();
343 setName(name);
344 }
345
346
347
348
349
350
351 @Deprecated
352 public HTableDescriptor(final byte[] name) {
353 this(TableName.valueOf(name));
354 }
355
356
357
358
359
360
361 @Deprecated
362 public HTableDescriptor(final String name) {
363 this(TableName.valueOf(name));
364 }
365
366
367
368
369
370
371
372
373 public HTableDescriptor(final HTableDescriptor desc) {
374 this(desc.name, desc);
375 }
376
377
378
379
380
381
382
383
384
385
386 public HTableDescriptor(final TableName name, final HTableDescriptor desc) {
387 super();
388 setName(name);
389 setMetaFlags(this.name);
390 for (HColumnDescriptor c: desc.families.values()) {
391 this.families.put(c.getName(), new HColumnDescriptor(c));
392 }
393 for (Map.Entry<ImmutableBytesWritable, ImmutableBytesWritable> e:
394 desc.values.entrySet()) {
395 setValue(e.getKey(), e.getValue());
396 }
397 for (Map.Entry<String, String> e : desc.configuration.entrySet()) {
398 this.configuration.put(e.getKey(), e.getValue());
399 }
400 }
401
402
403
404
405
406
407
408
409 private void setMetaFlags(final TableName name) {
410 setMetaRegion(isRootRegion() ||
411 name.equals(TableName.META_TABLE_NAME));
412 }
413
414
415
416
417
418
419 public boolean isRootRegion() {
420 if (this.root == null) {
421 this.root = isSomething(IS_ROOT_KEY, false)? Boolean.TRUE: Boolean.FALSE;
422 }
423 return this.root.booleanValue();
424 }
425
426
427
428
429
430
431
432
433 protected void setRootRegion(boolean isRoot) {
434
435 setValue(IS_ROOT_KEY, isRoot ? TRUE : FALSE);
436 }
437
438
439
440
441
442
443
444
445 public boolean isMetaRegion() {
446 if (this.meta == null) {
447 this.meta = calculateIsMetaRegion();
448 }
449 return this.meta.booleanValue();
450 }
451
452 private synchronized Boolean calculateIsMetaRegion() {
453 byte [] value = getValue(IS_META_KEY);
454 return (value != null)? Boolean.valueOf(Bytes.toString(value)): Boolean.FALSE;
455 }
456
457 private boolean isSomething(final ImmutableBytesWritable key,
458 final boolean valueIfNull) {
459 byte [] value = getValue(key);
460 if (value != null) {
461 return Boolean.valueOf(Bytes.toString(value));
462 }
463 return valueIfNull;
464 }
465
466
467
468
469
470
471
472
473
474 protected void setMetaRegion(boolean isMeta) {
475 setValue(IS_META_KEY, isMeta? TRUE: FALSE);
476 }
477
478
479
480
481
482
483 public boolean isMetaTable() {
484 return isMetaRegion() && !isRootRegion();
485 }
486
487
488
489
490
491
492
493
494 public byte[] getValue(byte[] key) {
495 return getValue(new ImmutableBytesWritable(key));
496 }
497
498 private byte[] getValue(final ImmutableBytesWritable key) {
499 ImmutableBytesWritable ibw = values.get(key);
500 if (ibw == null)
501 return null;
502 return ibw.get();
503 }
504
505
506
507
508
509
510
511
512 public String getValue(String key) {
513 byte[] value = getValue(Bytes.toBytes(key));
514 if (value == null)
515 return null;
516 return Bytes.toString(value);
517 }
518
519
520
521
522
523
524
525 public Map<ImmutableBytesWritable,ImmutableBytesWritable> getValues() {
526
527 return Collections.unmodifiableMap(values);
528 }
529
530
531
532
533
534
535
536
537 public HTableDescriptor setValue(byte[] key, byte[] value) {
538 setValue(new ImmutableBytesWritable(key), new ImmutableBytesWritable(value));
539 return this;
540 }
541
542
543
544
545
546 private HTableDescriptor setValue(final ImmutableBytesWritable key,
547 final String value) {
548 setValue(key, new ImmutableBytesWritable(Bytes.toBytes(value)));
549 return this;
550 }
551
552
553
554
555
556
557
558 public HTableDescriptor setValue(final ImmutableBytesWritable key,
559 final ImmutableBytesWritable value) {
560 if (key.compareTo(DEFERRED_LOG_FLUSH_KEY) == 0) {
561 boolean isDeferredFlush = Boolean.valueOf(Bytes.toString(value.get()));
562 LOG.warn("HTableDescriptor property:" + DEFERRED_LOG_FLUSH + " is deprecated, " +
563 "use " + DURABILITY + " instead");
564 setDurability(isDeferredFlush ? Durability.ASYNC_WAL : DEFAULT_DURABLITY);
565 return this;
566 }
567 values.put(key, value);
568 return this;
569 }
570
571
572
573
574
575
576
577
578 public HTableDescriptor setValue(String key, String value) {
579 if (value == null) {
580 remove(key);
581 } else {
582 setValue(Bytes.toBytes(key), Bytes.toBytes(value));
583 }
584 return this;
585 }
586
587
588
589
590
591
592
593 public void remove(final String key) {
594 remove(new ImmutableBytesWritable(Bytes.toBytes(key)));
595 }
596
597
598
599
600
601
602
603 public void remove(ImmutableBytesWritable key) {
604 values.remove(key);
605 }
606
607
608
609
610
611
612
613 public void remove(final byte [] key) {
614 remove(new ImmutableBytesWritable(key));
615 }
616
617
618
619
620
621
622
623 public boolean isReadOnly() {
624 return isSomething(READONLY_KEY, DEFAULT_READONLY);
625 }
626
627
628
629
630
631
632
633
634
635 public HTableDescriptor setReadOnly(final boolean readOnly) {
636 return setValue(READONLY_KEY, readOnly? TRUE: FALSE);
637 }
638
639
640
641
642
643
644
645 public boolean isCompactionEnabled() {
646 return isSomething(COMPACTION_ENABLED_KEY, DEFAULT_COMPACTION_ENABLED);
647 }
648
649
650
651
652
653
654 public HTableDescriptor setCompactionEnabled(final boolean isEnable) {
655 setValue(COMPACTION_ENABLED_KEY, isEnable ? TRUE : FALSE);
656 return this;
657 }
658
659
660
661
662
663
664
665 public boolean isNormalizationEnabled() {
666 return isSomething(NORMALIZATION_ENABLED_KEY, DEFAULT_NORMALIZATION_ENABLED);
667 }
668
669
670
671
672
673
674 public HTableDescriptor setNormalizationEnabled(final boolean isEnable) {
675 setValue(NORMALIZATION_ENABLED_KEY, isEnable ? TRUE : FALSE);
676 return this;
677 }
678
679
680
681
682
683 public HTableDescriptor setDurability(Durability durability) {
684 this.durability = durability;
685 setValue(DURABILITY_KEY, durability.name());
686 return this;
687 }
688
689
690
691
692
693 public Durability getDurability() {
694 if (this.durability == null) {
695 byte[] durabilityValue = getValue(DURABILITY_KEY);
696 if (durabilityValue == null) {
697 this.durability = DEFAULT_DURABLITY;
698 } else {
699 try {
700 this.durability = Durability.valueOf(Bytes.toString(durabilityValue));
701 } catch (IllegalArgumentException ex) {
702 LOG.warn("Received " + ex + " because Durability value for HTableDescriptor"
703 + " is not known. Durability:" + Bytes.toString(durabilityValue));
704 this.durability = DEFAULT_DURABLITY;
705 }
706 }
707 }
708 return this.durability;
709 }
710
711
712
713
714
715
716 public TableName getTableName() {
717 return name;
718 }
719
720
721
722
723
724
725
726 @Deprecated
727 public byte[] getName() {
728 return name.getName();
729 }
730
731
732
733
734
735
736 public String getNameAsString() {
737 return name.getNameAsString();
738 }
739
740
741
742
743
744
745
746 public HTableDescriptor setRegionSplitPolicyClassName(String clazz) {
747 setValue(SPLIT_POLICY, clazz);
748 return this;
749 }
750
751
752
753
754
755
756
757
758
759 public String getRegionSplitPolicyClassName() {
760 return getValue(SPLIT_POLICY);
761 }
762
763
764
765
766
767
768 @Deprecated
769 public HTableDescriptor setName(byte[] name) {
770 setName(TableName.valueOf(name));
771 return this;
772 }
773
774 @Deprecated
775 public HTableDescriptor setName(TableName name) {
776 this.name = name;
777 setMetaFlags(this.name);
778 return this;
779 }
780
781
782
783
784
785
786
787
788
789
790 public long getMaxFileSize() {
791 byte [] value = getValue(MAX_FILESIZE_KEY);
792 if (value != null) {
793 return Long.parseLong(Bytes.toString(value));
794 }
795 return -1;
796 }
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813 public HTableDescriptor setMaxFileSize(long maxFileSize) {
814 setValue(MAX_FILESIZE_KEY, Long.toString(maxFileSize));
815 return this;
816 }
817
818
819
820
821
822
823
824
825 public long getMemStoreFlushSize() {
826 byte [] value = getValue(MEMSTORE_FLUSHSIZE_KEY);
827 if (value != null) {
828 return Long.parseLong(Bytes.toString(value));
829 }
830 return -1;
831 }
832
833
834
835
836
837
838
839 public HTableDescriptor setMemStoreFlushSize(long memstoreFlushSize) {
840 setValue(MEMSTORE_FLUSHSIZE_KEY, Long.toString(memstoreFlushSize));
841 return this;
842 }
843
844
845
846
847
848
849
850 public HTableDescriptor setFlushPolicyClassName(String clazz) {
851 setValue(FLUSH_POLICY, clazz);
852 return this;
853 }
854
855
856
857
858
859
860
861
862 public String getFlushPolicyClassName() {
863 return getValue(FLUSH_POLICY);
864 }
865
866
867
868
869
870
871 public HTableDescriptor addFamily(final HColumnDescriptor family) {
872 if (family.getName() == null || family.getName().length <= 0) {
873 throw new IllegalArgumentException("Family name cannot be null or empty");
874 }
875 if (hasFamily(family.getName())) {
876 throw new IllegalArgumentException("Family '" +
877 family.getNameAsString() + "' already exists so cannot be added");
878 }
879 this.families.put(family.getName(), family);
880 return this;
881 }
882
883
884
885
886
887
888 public HTableDescriptor modifyFamily(final HColumnDescriptor family) {
889 if (family.getName() == null || family.getName().length <= 0) {
890 throw new IllegalArgumentException("Family name cannot be null or empty");
891 }
892 if (!hasFamily(family.getName())) {
893 throw new IllegalArgumentException("Column family '" + family.getNameAsString()
894 + "' does not exist");
895 }
896 this.families.put(family.getName(), family);
897 return this;
898 }
899
900
901
902
903
904
905 public boolean hasFamily(final byte [] familyName) {
906 return families.containsKey(familyName);
907 }
908
909
910
911
912
913
914 @Override
915 public String toString() {
916 StringBuilder s = new StringBuilder();
917 s.append('\'').append(Bytes.toString(name.getName())).append('\'');
918 s.append(getValues(true));
919 for (HColumnDescriptor f : families.values()) {
920 s.append(", ").append(f);
921 }
922 return s.toString();
923 }
924
925
926
927
928
929 public String toStringCustomizedValues() {
930 StringBuilder s = new StringBuilder();
931 s.append('\'').append(Bytes.toString(name.getName())).append('\'');
932 s.append(getValues(false));
933 for(HColumnDescriptor hcd : families.values()) {
934 s.append(", ").append(hcd.toStringCustomizedValues());
935 }
936 return s.toString();
937 }
938
939
940
941
942 public String toStringTableAttributes() {
943 return getValues(true).toString();
944 }
945
946 private StringBuilder getValues(boolean printDefaults) {
947 StringBuilder s = new StringBuilder();
948
949
950 Set<ImmutableBytesWritable> reservedKeys = new TreeSet<ImmutableBytesWritable>();
951 Set<ImmutableBytesWritable> userKeys = new TreeSet<ImmutableBytesWritable>();
952 for (Map.Entry<ImmutableBytesWritable, ImmutableBytesWritable> entry : values.entrySet()) {
953 ImmutableBytesWritable k = entry.getKey();
954 if (k == null || k.get() == null) continue;
955 String key = Bytes.toString(k.get());
956
957 if (!RESERVED_KEYWORDS.contains(k) && !key.startsWith("coprocessor$")) {
958 userKeys.add(k);
959 continue;
960 }
961
962 String value = Bytes.toString(entry.getValue().get());
963 if (key.equalsIgnoreCase(IS_ROOT) || key.equalsIgnoreCase(IS_META)) {
964 if (Boolean.valueOf(value) == false) continue;
965 }
966
967 if (printDefaults
968 || !DEFAULT_VALUES.containsKey(key)
969 || !DEFAULT_VALUES.get(key).equalsIgnoreCase(value)) {
970 reservedKeys.add(k);
971 }
972 }
973
974
975 boolean hasAttributes = !reservedKeys.isEmpty() || !userKeys.isEmpty();
976 if (!hasAttributes && configuration.isEmpty()) return s;
977
978 s.append(", {");
979
980 if (hasAttributes) {
981 s.append("TABLE_ATTRIBUTES => {");
982
983
984 boolean printCommaForAttr = false;
985 for (ImmutableBytesWritable k : reservedKeys) {
986 String key = Bytes.toString(k.get());
987 String value = Bytes.toStringBinary(values.get(k).get());
988 if (printCommaForAttr) s.append(", ");
989 printCommaForAttr = true;
990 s.append(key);
991 s.append(" => ");
992 s.append('\'').append(value).append('\'');
993 }
994
995 if (!userKeys.isEmpty()) {
996
997 if (printCommaForAttr) s.append(", ");
998 printCommaForAttr = true;
999 s.append(HConstants.METADATA).append(" => ");
1000 s.append("{");
1001 boolean printCommaForCfg = false;
1002 for (ImmutableBytesWritable k : userKeys) {
1003 String key = Bytes.toString(k.get());
1004 String value = Bytes.toStringBinary(values.get(k).get());
1005 if (printCommaForCfg) s.append(", ");
1006 printCommaForCfg = true;
1007 s.append('\'').append(key).append('\'');
1008 s.append(" => ");
1009 s.append('\'').append(value).append('\'');
1010 }
1011 s.append("}");
1012 }
1013 }
1014
1015
1016 if (!configuration.isEmpty()) {
1017 if (hasAttributes) {
1018 s.append(", ");
1019 }
1020 s.append(HConstants.CONFIGURATION).append(" => ");
1021 s.append('{');
1022 boolean printCommaForConfig = false;
1023 for (Map.Entry<String, String> e : configuration.entrySet()) {
1024 if (printCommaForConfig) s.append(", ");
1025 printCommaForConfig = true;
1026 s.append('\'').append(e.getKey()).append('\'');
1027 s.append(" => ");
1028 s.append('\'').append(e.getValue()).append('\'');
1029 }
1030 s.append("}");
1031 }
1032 s.append("}");
1033 return s;
1034 }
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045 @Override
1046 public boolean equals(Object obj) {
1047 if (this == obj) {
1048 return true;
1049 }
1050 if (obj == null) {
1051 return false;
1052 }
1053 if (!(obj instanceof HTableDescriptor)) {
1054 return false;
1055 }
1056 return compareTo((HTableDescriptor)obj) == 0;
1057 }
1058
1059
1060
1061
1062 @Override
1063 public int hashCode() {
1064 int result = this.name.hashCode();
1065 result ^= Byte.valueOf(TABLE_DESCRIPTOR_VERSION).hashCode();
1066 if (this.families != null && this.families.size() > 0) {
1067 for (HColumnDescriptor e: this.families.values()) {
1068 result ^= e.hashCode();
1069 }
1070 }
1071 result ^= values.hashCode();
1072 result ^= configuration.hashCode();
1073 return result;
1074 }
1075
1076
1077
1078
1079
1080
1081 @Deprecated
1082 @Override
1083 public void readFields(DataInput in) throws IOException {
1084 int version = in.readInt();
1085 if (version < 3)
1086 throw new IOException("versions < 3 are not supported (and never existed!?)");
1087
1088 name = TableName.valueOf(Bytes.readByteArray(in));
1089 setRootRegion(in.readBoolean());
1090 setMetaRegion(in.readBoolean());
1091 values.clear();
1092 configuration.clear();
1093 int numVals = in.readInt();
1094 for (int i = 0; i < numVals; i++) {
1095 ImmutableBytesWritable key = new ImmutableBytesWritable();
1096 ImmutableBytesWritable value = new ImmutableBytesWritable();
1097 key.readFields(in);
1098 value.readFields(in);
1099 setValue(key, value);
1100 }
1101 families.clear();
1102 int numFamilies = in.readInt();
1103 for (int i = 0; i < numFamilies; i++) {
1104 HColumnDescriptor c = new HColumnDescriptor();
1105 c.readFields(in);
1106 families.put(c.getName(), c);
1107 }
1108 if (version >= 7) {
1109 int numConfigs = in.readInt();
1110 for (int i = 0; i < numConfigs; i++) {
1111 ImmutableBytesWritable key = new ImmutableBytesWritable();
1112 ImmutableBytesWritable value = new ImmutableBytesWritable();
1113 key.readFields(in);
1114 value.readFields(in);
1115 configuration.put(
1116 Bytes.toString(key.get(), key.getOffset(), key.getLength()),
1117 Bytes.toString(value.get(), value.getOffset(), value.getLength()));
1118 }
1119 }
1120 }
1121
1122
1123
1124
1125
1126
1127
1128 @Deprecated
1129 @Override
1130 public void write(DataOutput out) throws IOException {
1131 out.writeInt(TABLE_DESCRIPTOR_VERSION);
1132 Bytes.writeByteArray(out, name.toBytes());
1133 out.writeBoolean(isRootRegion());
1134 out.writeBoolean(isMetaRegion());
1135 out.writeInt(values.size());
1136 for (Map.Entry<ImmutableBytesWritable, ImmutableBytesWritable> e:
1137 values.entrySet()) {
1138 e.getKey().write(out);
1139 e.getValue().write(out);
1140 }
1141 out.writeInt(families.size());
1142 for(Iterator<HColumnDescriptor> it = families.values().iterator();
1143 it.hasNext(); ) {
1144 HColumnDescriptor family = it.next();
1145 family.write(out);
1146 }
1147 out.writeInt(configuration.size());
1148 for (Map.Entry<String, String> e : configuration.entrySet()) {
1149 new ImmutableBytesWritable(Bytes.toBytes(e.getKey())).write(out);
1150 new ImmutableBytesWritable(Bytes.toBytes(e.getValue())).write(out);
1151 }
1152 }
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163 @Override
1164 public int compareTo(final HTableDescriptor other) {
1165 int result = this.name.compareTo(other.name);
1166 if (result == 0) {
1167 result = families.size() - other.families.size();
1168 }
1169 if (result == 0 && families.size() != other.families.size()) {
1170 result = Integer.compare(families.size(), other.families.size());
1171 }
1172 if (result == 0) {
1173 for (Iterator<HColumnDescriptor> it = families.values().iterator(),
1174 it2 = other.families.values().iterator(); it.hasNext(); ) {
1175 result = it.next().compareTo(it2.next());
1176 if (result != 0) {
1177 break;
1178 }
1179 }
1180 }
1181 if (result == 0) {
1182
1183 result = this.values.hashCode() - other.values.hashCode();
1184 if (result < 0)
1185 result = -1;
1186 else if (result > 0)
1187 result = 1;
1188 }
1189 if (result == 0) {
1190 result = this.configuration.hashCode() - other.configuration.hashCode();
1191 if (result < 0)
1192 result = -1;
1193 else if (result > 0)
1194 result = 1;
1195 }
1196 return result;
1197 }
1198
1199
1200
1201
1202
1203
1204
1205
1206 public Collection<HColumnDescriptor> getFamilies() {
1207 return Collections.unmodifiableCollection(this.families.values());
1208 }
1209
1210
1211
1212
1213 public int getRegionReplication() {
1214 byte[] val = getValue(REGION_REPLICATION_KEY);
1215 if (val == null || val.length == 0) {
1216 return DEFAULT_REGION_REPLICATION;
1217 }
1218 return Integer.parseInt(Bytes.toString(val));
1219 }
1220
1221
1222
1223
1224
1225 public HTableDescriptor setRegionReplication(int regionReplication) {
1226 setValue(REGION_REPLICATION_KEY,
1227 new ImmutableBytesWritable(Bytes.toBytes(Integer.toString(regionReplication))));
1228 return this;
1229 }
1230
1231
1232
1233
1234 public boolean hasRegionMemstoreReplication() {
1235 return isSomething(REGION_MEMSTORE_REPLICATION_KEY, DEFAULT_REGION_MEMSTORE_REPLICATION);
1236 }
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247 public HTableDescriptor setRegionMemstoreReplication(boolean memstoreReplication) {
1248 setValue(REGION_MEMSTORE_REPLICATION_KEY, memstoreReplication ? TRUE : FALSE);
1249
1250
1251 setConfiguration(RegionReplicaUtil.REGION_REPLICA_WAIT_FOR_PRIMARY_FLUSH_CONF_KEY,
1252 Boolean.toString(memstoreReplication));
1253 return this;
1254 }
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264 public Set<byte[]> getFamiliesKeys() {
1265 return Collections.unmodifiableSet(this.families.keySet());
1266 }
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276 public HColumnDescriptor[] getColumnFamilies() {
1277 Collection<HColumnDescriptor> hColumnDescriptors = getFamilies();
1278 return hColumnDescriptors.toArray(new HColumnDescriptor[hColumnDescriptors.size()]);
1279 }
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290 public HColumnDescriptor getFamily(final byte [] column) {
1291 return this.families.get(column);
1292 }
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303 public HColumnDescriptor removeFamily(final byte [] column) {
1304 return this.families.remove(column);
1305 }
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317 public HTableDescriptor addCoprocessor(String className) throws IOException {
1318 addCoprocessor(className, null, Coprocessor.PRIORITY_USER, null);
1319 return this;
1320 }
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336 public HTableDescriptor addCoprocessor(String className, Path jarFilePath,
1337 int priority, final Map<String, String> kvs)
1338 throws IOException {
1339 checkHasCoprocessor(className);
1340
1341
1342 StringBuilder kvString = new StringBuilder();
1343 if (kvs != null) {
1344 for (Map.Entry<String, String> e: kvs.entrySet()) {
1345 if (!e.getKey().matches(HConstants.CP_HTD_ATTR_VALUE_PARAM_KEY_PATTERN)) {
1346 throw new IOException("Illegal parameter key = " + e.getKey());
1347 }
1348 if (!e.getValue().matches(HConstants.CP_HTD_ATTR_VALUE_PARAM_VALUE_PATTERN)) {
1349 throw new IOException("Illegal parameter (" + e.getKey() +
1350 ") value = " + e.getValue());
1351 }
1352 if (kvString.length() != 0) {
1353 kvString.append(',');
1354 }
1355 kvString.append(e.getKey());
1356 kvString.append('=');
1357 kvString.append(e.getValue());
1358 }
1359 }
1360
1361 String value = ((jarFilePath == null)? "" : jarFilePath.toString()) +
1362 "|" + className + "|" + Integer.toString(priority) + "|" +
1363 kvString.toString();
1364 return addCoprocessorToMap(value);
1365 }
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378 public HTableDescriptor addCoprocessorWithSpec(final String specStr) throws IOException {
1379 String className = getCoprocessorClassNameFromSpecStr(specStr);
1380 if (className == null) {
1381 throw new IllegalArgumentException("Format does not match " +
1382 HConstants.CP_HTD_ATTR_VALUE_PATTERN + ": " + specStr);
1383 }
1384 checkHasCoprocessor(className);
1385 return addCoprocessorToMap(specStr);
1386 }
1387
1388 private void checkHasCoprocessor(final String className) throws IOException {
1389 if (hasCoprocessor(className)) {
1390 throw new IOException("Coprocessor " + className + " already exists.");
1391 }
1392 }
1393
1394
1395
1396
1397
1398
1399
1400 private HTableDescriptor addCoprocessorToMap(final String specStr) {
1401 if (specStr == null) return this;
1402
1403 int maxCoprocessorNumber = 0;
1404 Matcher keyMatcher;
1405 for (Map.Entry<ImmutableBytesWritable, ImmutableBytesWritable> e:
1406 this.values.entrySet()) {
1407 keyMatcher =
1408 HConstants.CP_HTD_ATTR_KEY_PATTERN.matcher(
1409 Bytes.toString(e.getKey().get()));
1410 if (!keyMatcher.matches()) {
1411 continue;
1412 }
1413 maxCoprocessorNumber = Math.max(Integer.parseInt(keyMatcher.group(1)), maxCoprocessorNumber);
1414 }
1415 maxCoprocessorNumber++;
1416 String key = "coprocessor$" + Integer.toString(maxCoprocessorNumber);
1417 this.values.put(new ImmutableBytesWritable(Bytes.toBytes(key)),
1418 new ImmutableBytesWritable(Bytes.toBytes(specStr)));
1419 return this;
1420 }
1421
1422
1423
1424
1425
1426
1427
1428 public boolean hasCoprocessor(String classNameToMatch) {
1429 Matcher keyMatcher;
1430 Matcher valueMatcher;
1431 for (Map.Entry<ImmutableBytesWritable, ImmutableBytesWritable> e:
1432 this.values.entrySet()) {
1433 keyMatcher =
1434 HConstants.CP_HTD_ATTR_KEY_PATTERN.matcher(
1435 Bytes.toString(e.getKey().get()));
1436 if (!keyMatcher.matches()) {
1437 continue;
1438 }
1439 String className = getCoprocessorClassNameFromSpecStr(Bytes.toString(e.getValue().get()));
1440 if (className == null) continue;
1441 if (className.equals(classNameToMatch.trim())) {
1442 return true;
1443 }
1444 }
1445 return false;
1446 }
1447
1448
1449
1450
1451
1452
1453 public List<String> getCoprocessors() {
1454 List<String> result = new ArrayList<String>();
1455 Matcher keyMatcher;
1456 Matcher valueMatcher;
1457 for (Map.Entry<ImmutableBytesWritable, ImmutableBytesWritable> e : this.values.entrySet()) {
1458 keyMatcher = HConstants.CP_HTD_ATTR_KEY_PATTERN.matcher(Bytes.toString(e.getKey().get()));
1459 if (!keyMatcher.matches()) {
1460 continue;
1461 }
1462 String className = getCoprocessorClassNameFromSpecStr(Bytes.toString(e.getValue().get()));
1463 if (className == null) continue;
1464 result.add(className);
1465 }
1466 return result;
1467 }
1468
1469
1470
1471
1472
1473 private static String getCoprocessorClassNameFromSpecStr(final String spec) {
1474 Matcher matcher = HConstants.CP_HTD_ATTR_VALUE_PATTERN.matcher(spec);
1475
1476 return matcher != null && matcher.matches()? matcher.group(2).trim(): null;
1477 }
1478
1479
1480
1481
1482
1483 public void removeCoprocessor(String className) {
1484 ImmutableBytesWritable match = null;
1485 Matcher keyMatcher;
1486 Matcher valueMatcher;
1487 for (Map.Entry<ImmutableBytesWritable, ImmutableBytesWritable> e : this.values
1488 .entrySet()) {
1489 keyMatcher = HConstants.CP_HTD_ATTR_KEY_PATTERN.matcher(Bytes.toString(e
1490 .getKey().get()));
1491 if (!keyMatcher.matches()) {
1492 continue;
1493 }
1494 valueMatcher = HConstants.CP_HTD_ATTR_VALUE_PATTERN.matcher(Bytes
1495 .toString(e.getValue().get()));
1496 if (!valueMatcher.matches()) {
1497 continue;
1498 }
1499
1500 String clazz = valueMatcher.group(2).trim();
1501
1502 if (clazz.equals(className.trim())) {
1503 match = e.getKey();
1504 break;
1505 }
1506 }
1507
1508 if (match != null)
1509 remove(match);
1510 }
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522 @Deprecated
1523 public static Path getTableDir(Path rootdir, final byte [] tableName) {
1524
1525
1526 TableName name = TableName.valueOf(tableName);
1527 return new Path(rootdir, new Path(HConstants.BASE_NAMESPACE_DIR,
1528 new Path(name.getNamespaceAsString(), new Path(name.getQualifierAsString()))));
1529 }
1530
1531
1532
1533
1534
1535
1536 @Deprecated
1537 public static final HTableDescriptor META_TABLEDESC = new HTableDescriptor(
1538 TableName.META_TABLE_NAME,
1539 new HColumnDescriptor[] {
1540 new HColumnDescriptor(HConstants.CATALOG_FAMILY)
1541
1542 .setMaxVersions(HConstants.DEFAULT_HBASE_META_VERSIONS)
1543 .setInMemory(true)
1544 .setBlocksize(HConstants.DEFAULT_HBASE_META_BLOCK_SIZE)
1545 .setScope(HConstants.REPLICATION_SCOPE_LOCAL)
1546
1547 .setBloomFilterType(BloomType.NONE)
1548
1549
1550 .setCacheDataInL1(true)
1551 });
1552
1553 static {
1554 try {
1555 META_TABLEDESC.addCoprocessor(
1556 "org.apache.hadoop.hbase.coprocessor.MultiRowMutationEndpoint",
1557 null, Coprocessor.PRIORITY_SYSTEM, null);
1558 } catch (IOException ex) {
1559
1560 throw new RuntimeException(ex);
1561 }
1562 }
1563
1564 public final static String NAMESPACE_FAMILY_INFO = "info";
1565 public final static byte[] NAMESPACE_FAMILY_INFO_BYTES = Bytes.toBytes(NAMESPACE_FAMILY_INFO);
1566 public final static byte[] NAMESPACE_COL_DESC_BYTES = Bytes.toBytes("d");
1567
1568
1569 public static final HTableDescriptor NAMESPACE_TABLEDESC = new HTableDescriptor(
1570 TableName.NAMESPACE_TABLE_NAME,
1571 new HColumnDescriptor[] {
1572 new HColumnDescriptor(NAMESPACE_FAMILY_INFO)
1573
1574 .setMaxVersions(10)
1575 .setInMemory(true)
1576 .setBlocksize(8 * 1024)
1577 .setScope(HConstants.REPLICATION_SCOPE_LOCAL)
1578
1579
1580 .setCacheDataInL1(true)
1581 });
1582
1583 @Deprecated
1584 public HTableDescriptor setOwner(User owner) {
1585 return setOwnerString(owner != null ? owner.getShortName() : null);
1586 }
1587
1588
1589 @Deprecated
1590 public HTableDescriptor setOwnerString(String ownerString) {
1591 if (ownerString != null) {
1592 setValue(OWNER_KEY, ownerString);
1593 } else {
1594 remove(OWNER_KEY);
1595 }
1596 return this;
1597 }
1598
1599 @Deprecated
1600 public String getOwnerString() {
1601 if (getValue(OWNER_KEY) != null) {
1602 return Bytes.toString(getValue(OWNER_KEY));
1603 }
1604
1605
1606
1607 return null;
1608 }
1609
1610
1611
1612
1613
1614 public byte [] toByteArray() {
1615 return ProtobufUtil.prependPBMagic(convert().toByteArray());
1616 }
1617
1618
1619
1620
1621
1622
1623
1624
1625 public static HTableDescriptor parseFrom(final byte [] bytes)
1626 throws DeserializationException, IOException {
1627 if (!ProtobufUtil.isPBMagicPrefix(bytes)) {
1628 return (HTableDescriptor)Writables.getWritable(bytes, new HTableDescriptor());
1629 }
1630 int pblen = ProtobufUtil.lengthOfPBMagic();
1631 TableSchema.Builder builder = TableSchema.newBuilder();
1632 TableSchema ts;
1633 try {
1634 ProtobufUtil.mergeFrom(builder, bytes, pblen, bytes.length - pblen);
1635 ts = builder.build();
1636 } catch (IOException e) {
1637 throw new DeserializationException(e);
1638 }
1639 return convert(ts);
1640 }
1641
1642
1643
1644
1645 public TableSchema convert() {
1646 TableSchema.Builder builder = TableSchema.newBuilder();
1647 builder.setTableName(ProtobufUtil.toProtoTableName(getTableName()));
1648 for (Map.Entry<ImmutableBytesWritable, ImmutableBytesWritable> e: this.values.entrySet()) {
1649 BytesBytesPair.Builder aBuilder = BytesBytesPair.newBuilder();
1650 aBuilder.setFirst(ByteStringer.wrap(e.getKey().get()));
1651 aBuilder.setSecond(ByteStringer.wrap(e.getValue().get()));
1652 builder.addAttributes(aBuilder.build());
1653 }
1654 for (HColumnDescriptor hcd: getColumnFamilies()) {
1655 builder.addColumnFamilies(hcd.convert());
1656 }
1657 for (Map.Entry<String, String> e : this.configuration.entrySet()) {
1658 NameStringPair.Builder aBuilder = NameStringPair.newBuilder();
1659 aBuilder.setName(e.getKey());
1660 aBuilder.setValue(e.getValue());
1661 builder.addConfiguration(aBuilder.build());
1662 }
1663 return builder.build();
1664 }
1665
1666
1667
1668
1669
1670 public static HTableDescriptor convert(final TableSchema ts) {
1671 List<ColumnFamilySchema> list = ts.getColumnFamiliesList();
1672 HColumnDescriptor [] hcds = new HColumnDescriptor[list.size()];
1673 int index = 0;
1674 for (ColumnFamilySchema cfs: list) {
1675 hcds[index++] = HColumnDescriptor.convert(cfs);
1676 }
1677 HTableDescriptor htd = new HTableDescriptor(
1678 ProtobufUtil.toTableName(ts.getTableName()),
1679 hcds);
1680 for (BytesBytesPair a: ts.getAttributesList()) {
1681 htd.setValue(a.getFirst().toByteArray(), a.getSecond().toByteArray());
1682 }
1683 for (NameStringPair a: ts.getConfigurationList()) {
1684 htd.setConfiguration(a.getName(), a.getValue());
1685 }
1686 return htd;
1687 }
1688
1689
1690
1691
1692 public String getConfigurationValue(String key) {
1693 return configuration.get(key);
1694 }
1695
1696
1697
1698
1699 public Map<String, String> getConfiguration() {
1700
1701 return Collections.unmodifiableMap(configuration);
1702 }
1703
1704
1705
1706
1707
1708
1709 public HTableDescriptor setConfiguration(String key, String value) {
1710 if (value == null) {
1711 removeConfiguration(key);
1712 } else {
1713 configuration.put(key, value);
1714 }
1715 return this;
1716 }
1717
1718
1719
1720
1721 public void removeConfiguration(final String key) {
1722 configuration.remove(key);
1723 }
1724
1725 public static HTableDescriptor metaTableDescriptor(final Configuration conf)
1726 throws IOException {
1727 HTableDescriptor metaDescriptor = new HTableDescriptor(
1728 TableName.META_TABLE_NAME,
1729 new HColumnDescriptor[] {
1730 new HColumnDescriptor(HConstants.CATALOG_FAMILY)
1731 .setMaxVersions(conf.getInt(HConstants.HBASE_META_VERSIONS,
1732 HConstants.DEFAULT_HBASE_META_VERSIONS))
1733 .setInMemory(true)
1734 .setBlocksize(conf.getInt(HConstants.HBASE_META_BLOCK_SIZE,
1735 HConstants.DEFAULT_HBASE_META_BLOCK_SIZE))
1736 .setScope(HConstants.REPLICATION_SCOPE_LOCAL)
1737
1738 .setBloomFilterType(BloomType.NONE)
1739 .setCacheDataInL1(true)
1740 });
1741 metaDescriptor.addCoprocessor(
1742 "org.apache.hadoop.hbase.coprocessor.MultiRowMutationEndpoint",
1743 null, Coprocessor.PRIORITY_SYSTEM, null);
1744 return metaDescriptor;
1745 }
1746
1747 }