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