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 void setValue(byte[] key, byte[] value) {
538 setValue(new ImmutableBytesWritable(key), new ImmutableBytesWritable(value));
539 }
540
541
542
543
544
545 private void setValue(final ImmutableBytesWritable key,
546 final String value) {
547 setValue(key, new ImmutableBytesWritable(Bytes.toBytes(value)));
548 }
549
550
551
552
553
554
555
556 public void setValue(final ImmutableBytesWritable key,
557 final ImmutableBytesWritable value) {
558 if (key.compareTo(DEFERRED_LOG_FLUSH_KEY) == 0) {
559 boolean isDeferredFlush = Boolean.valueOf(Bytes.toString(value.get()));
560 LOG.warn("HTableDescriptor property:" + DEFERRED_LOG_FLUSH + " is deprecated, " +
561 "use " + DURABILITY + " instead");
562 setDurability(isDeferredFlush ? Durability.ASYNC_WAL : DEFAULT_DURABLITY);
563 } else {
564 values.put(key, value);
565 }
566 }
567
568
569
570
571
572
573
574
575 public void setValue(String key, String value) {
576 if (value == null) {
577 remove(key);
578 } else {
579 setValue(Bytes.toBytes(key), Bytes.toBytes(value));
580 }
581 }
582
583
584
585
586
587
588
589 public void remove(final String key) {
590 remove(new ImmutableBytesWritable(Bytes.toBytes(key)));
591 }
592
593
594
595
596
597
598
599 public void remove(ImmutableBytesWritable key) {
600 values.remove(key);
601 }
602
603
604
605
606
607
608
609 public void remove(final byte [] key) {
610 remove(new ImmutableBytesWritable(key));
611 }
612
613
614
615
616
617
618
619 public boolean isReadOnly() {
620 return isSomething(READONLY_KEY, DEFAULT_READONLY);
621 }
622
623
624
625
626
627
628
629
630
631 public void setReadOnly(final boolean readOnly) {
632 setValue(READONLY_KEY, readOnly? TRUE: FALSE);
633 }
634
635
636
637
638
639
640
641 public boolean isCompactionEnabled() {
642 return isSomething(COMPACTION_ENABLED_KEY, DEFAULT_COMPACTION_ENABLED);
643 }
644
645
646
647
648
649
650 public void setCompactionEnabled(final boolean isEnable) {
651 setValue(COMPACTION_ENABLED_KEY, isEnable ? TRUE : FALSE);
652 }
653
654
655
656
657
658
659
660 public boolean isNormalizationEnabled() {
661 return isSomething(NORMALIZATION_ENABLED_KEY, DEFAULT_NORMALIZATION_ENABLED);
662 }
663
664
665
666
667
668
669 public HTableDescriptor setNormalizationEnabled(final boolean isEnable) {
670 setValue(NORMALIZATION_ENABLED_KEY, isEnable ? TRUE : FALSE);
671 return this;
672 }
673
674
675
676
677
678
679 @Deprecated
680 public synchronized boolean isDeferredLogFlush() {
681 return getDurability() == Durability.ASYNC_WAL;
682 }
683
684
685
686
687
688
689 @Deprecated
690 public synchronized void setDeferredLogFlush(final boolean isAsyncLogFlush) {
691 this.setDurability(isAsyncLogFlush ? Durability.ASYNC_WAL : DEFAULT_DURABLITY);
692 }
693
694
695
696
697
698 public void setDurability(Durability durability) {
699 this.durability = durability;
700 setValue(DURABILITY_KEY, durability.name());
701 }
702
703
704
705
706
707 public Durability getDurability() {
708 if (this.durability == null) {
709 byte[] durabilityValue = getValue(DURABILITY_KEY);
710 if (durabilityValue == null) {
711 this.durability = DEFAULT_DURABLITY;
712 } else {
713 try {
714 this.durability = Durability.valueOf(Bytes.toString(durabilityValue));
715 } catch (IllegalArgumentException ex) {
716 LOG.warn("Received " + ex + " because Durability value for HTableDescriptor"
717 + " is not known. Durability:" + Bytes.toString(durabilityValue));
718 this.durability = DEFAULT_DURABLITY;
719 }
720 }
721 }
722 return this.durability;
723 }
724
725
726
727
728
729
730 public TableName getTableName() {
731 return name;
732 }
733
734
735
736
737
738
739
740 @Deprecated
741 public byte[] getName() {
742 return name.getName();
743 }
744
745
746
747
748
749
750 public String getNameAsString() {
751 return name.getNameAsString();
752 }
753
754
755
756
757
758
759
760 public HTableDescriptor setRegionSplitPolicyClassName(String clazz) {
761 setValue(SPLIT_POLICY, clazz);
762 return this;
763 }
764
765
766
767
768
769
770
771
772
773 public String getRegionSplitPolicyClassName() {
774 return getValue(SPLIT_POLICY);
775 }
776
777
778
779
780
781
782 @Deprecated
783 public void setName(byte[] name) {
784 setName(TableName.valueOf(name));
785 }
786
787 @Deprecated
788 public void setName(TableName name) {
789 this.name = name;
790 setMetaFlags(this.name);
791 }
792
793
794
795
796
797
798
799
800
801
802 public long getMaxFileSize() {
803 byte [] value = getValue(MAX_FILESIZE_KEY);
804 if (value != null) {
805 return Long.parseLong(Bytes.toString(value));
806 }
807 return -1;
808 }
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825 public void setMaxFileSize(long maxFileSize) {
826 setValue(MAX_FILESIZE_KEY, Long.toString(maxFileSize));
827 }
828
829
830
831
832
833
834
835
836 public long getMemStoreFlushSize() {
837 byte [] value = getValue(MEMSTORE_FLUSHSIZE_KEY);
838 if (value != null) {
839 return Long.parseLong(Bytes.toString(value));
840 }
841 return -1;
842 }
843
844
845
846
847
848
849
850 public void setMemStoreFlushSize(long memstoreFlushSize) {
851 setValue(MEMSTORE_FLUSHSIZE_KEY, Long.toString(memstoreFlushSize));
852 }
853
854
855
856
857
858
859
860 public HTableDescriptor setFlushPolicyClassName(String clazz) {
861 setValue(FLUSH_POLICY, clazz);
862 return this;
863 }
864
865
866
867
868
869
870
871
872 public String getFlushPolicyClassName() {
873 return getValue(FLUSH_POLICY);
874 }
875
876
877
878
879
880
881 public void addFamily(final HColumnDescriptor family) {
882 if (family.getName() == null || family.getName().length <= 0) {
883 throw new IllegalArgumentException("Family name cannot be null or empty");
884 }
885 if (hasFamily(family.getName())) {
886 throw new IllegalArgumentException("Family '" +
887 family.getNameAsString() + "' already exists so cannot be added");
888 }
889 this.families.put(family.getName(), family);
890 }
891
892
893
894
895
896
897 public HTableDescriptor modifyFamily(final HColumnDescriptor family) {
898 if (family.getName() == null || family.getName().length <= 0) {
899 throw new IllegalArgumentException("Family name cannot be null or empty");
900 }
901 if (!hasFamily(family.getName())) {
902 throw new IllegalArgumentException("Column family '" + family.getNameAsString()
903 + "' does not exist");
904 }
905 this.families.put(family.getName(), family);
906 return this;
907 }
908
909
910
911
912
913
914 public boolean hasFamily(final byte [] familyName) {
915 return families.containsKey(familyName);
916 }
917
918
919
920
921
922
923 @Override
924 public String toString() {
925 StringBuilder s = new StringBuilder();
926 s.append('\'').append(Bytes.toString(name.getName())).append('\'');
927 s.append(getValues(true));
928 for (HColumnDescriptor f : families.values()) {
929 s.append(", ").append(f);
930 }
931 return s.toString();
932 }
933
934
935
936
937
938 public String toStringCustomizedValues() {
939 StringBuilder s = new StringBuilder();
940 s.append('\'').append(Bytes.toString(name.getName())).append('\'');
941 s.append(getValues(false));
942 for(HColumnDescriptor hcd : families.values()) {
943 s.append(", ").append(hcd.toStringCustomizedValues());
944 }
945 return s.toString();
946 }
947
948
949
950
951 public String toStringTableAttributes() {
952 return getValues(true).toString();
953 }
954
955 private StringBuilder getValues(boolean printDefaults) {
956 StringBuilder s = new StringBuilder();
957
958
959 Set<ImmutableBytesWritable> reservedKeys = new TreeSet<ImmutableBytesWritable>();
960 Set<ImmutableBytesWritable> userKeys = new TreeSet<ImmutableBytesWritable>();
961 for (ImmutableBytesWritable k : values.keySet()) {
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(values.get(k).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 @Override
1071 public int hashCode() {
1072 int result = this.name.hashCode();
1073 result ^= Byte.valueOf(TABLE_DESCRIPTOR_VERSION).hashCode();
1074 if (this.families != null && this.families.size() > 0) {
1075 for (HColumnDescriptor e: this.families.values()) {
1076 result ^= e.hashCode();
1077 }
1078 }
1079 result ^= values.hashCode();
1080 result ^= configuration.hashCode();
1081 return result;
1082 }
1083
1084
1085
1086
1087
1088
1089 @Deprecated
1090 @Override
1091 public void readFields(DataInput in) throws IOException {
1092 int version = in.readInt();
1093 if (version < 3)
1094 throw new IOException("versions < 3 are not supported (and never existed!?)");
1095
1096 name = TableName.valueOf(Bytes.readByteArray(in));
1097 setRootRegion(in.readBoolean());
1098 setMetaRegion(in.readBoolean());
1099 values.clear();
1100 configuration.clear();
1101 int numVals = in.readInt();
1102 for (int i = 0; i < numVals; i++) {
1103 ImmutableBytesWritable key = new ImmutableBytesWritable();
1104 ImmutableBytesWritable value = new ImmutableBytesWritable();
1105 key.readFields(in);
1106 value.readFields(in);
1107 setValue(key, value);
1108 }
1109 families.clear();
1110 int numFamilies = in.readInt();
1111 for (int i = 0; i < numFamilies; i++) {
1112 HColumnDescriptor c = new HColumnDescriptor();
1113 c.readFields(in);
1114 families.put(c.getName(), c);
1115 }
1116 if (version >= 7) {
1117 int numConfigs = in.readInt();
1118 for (int i = 0; i < numConfigs; i++) {
1119 ImmutableBytesWritable key = new ImmutableBytesWritable();
1120 ImmutableBytesWritable value = new ImmutableBytesWritable();
1121 key.readFields(in);
1122 value.readFields(in);
1123 configuration.put(
1124 Bytes.toString(key.get(), key.getOffset(), key.getLength()),
1125 Bytes.toString(value.get(), value.getOffset(), value.getLength()));
1126 }
1127 }
1128 }
1129
1130
1131
1132
1133
1134
1135
1136 @Deprecated
1137 @Override
1138 public void write(DataOutput out) throws IOException {
1139 out.writeInt(TABLE_DESCRIPTOR_VERSION);
1140 Bytes.writeByteArray(out, name.toBytes());
1141 out.writeBoolean(isRootRegion());
1142 out.writeBoolean(isMetaRegion());
1143 out.writeInt(values.size());
1144 for (Map.Entry<ImmutableBytesWritable, ImmutableBytesWritable> e:
1145 values.entrySet()) {
1146 e.getKey().write(out);
1147 e.getValue().write(out);
1148 }
1149 out.writeInt(families.size());
1150 for(Iterator<HColumnDescriptor> it = families.values().iterator();
1151 it.hasNext(); ) {
1152 HColumnDescriptor family = it.next();
1153 family.write(out);
1154 }
1155 out.writeInt(configuration.size());
1156 for (Map.Entry<String, String> e : configuration.entrySet()) {
1157 new ImmutableBytesWritable(Bytes.toBytes(e.getKey())).write(out);
1158 new ImmutableBytesWritable(Bytes.toBytes(e.getValue())).write(out);
1159 }
1160 }
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171 @Override
1172 public int compareTo(final HTableDescriptor other) {
1173 int result = this.name.compareTo(other.name);
1174 if (result == 0) {
1175 result = families.size() - other.families.size();
1176 }
1177 if (result == 0 && families.size() != other.families.size()) {
1178 result = Integer.valueOf(families.size()).compareTo(
1179 Integer.valueOf(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 byte[] val = getValue(REGION_REPLICATION_KEY);
1224 if (val == null || val.length == 0) {
1225 return DEFAULT_REGION_REPLICATION;
1226 }
1227 return Integer.parseInt(Bytes.toString(val));
1228 }
1229
1230
1231
1232
1233
1234 public HTableDescriptor setRegionReplication(int regionReplication) {
1235 setValue(REGION_REPLICATION_KEY,
1236 new ImmutableBytesWritable(Bytes.toBytes(Integer.toString(regionReplication))));
1237 return this;
1238 }
1239
1240
1241
1242
1243 public boolean hasRegionMemstoreReplication() {
1244 return isSomething(REGION_MEMSTORE_REPLICATION_KEY, DEFAULT_REGION_MEMSTORE_REPLICATION);
1245 }
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256 public HTableDescriptor setRegionMemstoreReplication(boolean memstoreReplication) {
1257 setValue(REGION_MEMSTORE_REPLICATION_KEY, memstoreReplication ? TRUE : FALSE);
1258
1259
1260 setConfiguration(RegionReplicaUtil.REGION_REPLICA_WAIT_FOR_PRIMARY_FLUSH_CONF_KEY,
1261 Boolean.toString(memstoreReplication));
1262 return this;
1263 }
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273 public Set<byte[]> getFamiliesKeys() {
1274 return Collections.unmodifiableSet(this.families.keySet());
1275 }
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285 public HColumnDescriptor[] getColumnFamilies() {
1286 Collection<HColumnDescriptor> hColumnDescriptors = getFamilies();
1287 return hColumnDescriptors.toArray(new HColumnDescriptor[hColumnDescriptors.size()]);
1288 }
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299 public HColumnDescriptor getFamily(final byte [] column) {
1300 return this.families.get(column);
1301 }
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312 public HColumnDescriptor removeFamily(final byte [] column) {
1313 return this.families.remove(column);
1314 }
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326 public void addCoprocessor(String className) throws IOException {
1327 addCoprocessor(className, null, Coprocessor.PRIORITY_USER, null);
1328 }
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344 public void addCoprocessor(String className, Path jarFilePath,
1345 int priority, final Map<String, String> kvs)
1346 throws IOException {
1347 checkHasCoprocessor(className);
1348
1349
1350 StringBuilder kvString = new StringBuilder();
1351 if (kvs != null) {
1352 for (Map.Entry<String, String> e: kvs.entrySet()) {
1353 if (!e.getKey().matches(HConstants.CP_HTD_ATTR_VALUE_PARAM_KEY_PATTERN)) {
1354 throw new IOException("Illegal parameter key = " + e.getKey());
1355 }
1356 if (!e.getValue().matches(HConstants.CP_HTD_ATTR_VALUE_PARAM_VALUE_PATTERN)) {
1357 throw new IOException("Illegal parameter (" + e.getKey() +
1358 ") value = " + e.getValue());
1359 }
1360 if (kvString.length() != 0) {
1361 kvString.append(',');
1362 }
1363 kvString.append(e.getKey());
1364 kvString.append('=');
1365 kvString.append(e.getValue());
1366 }
1367 }
1368
1369 String value = ((jarFilePath == null)? "" : jarFilePath.toString()) +
1370 "|" + className + "|" + Integer.toString(priority) + "|" +
1371 kvString.toString();
1372 addCoprocessorToMap(value);
1373 }
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386 public HTableDescriptor addCoprocessorWithSpec(final String specStr) throws IOException {
1387 String className = getCoprocessorClassNameFromSpecStr(specStr);
1388 if (className == null) {
1389 throw new IllegalArgumentException("Format does not match " +
1390 HConstants.CP_HTD_ATTR_VALUE_PATTERN + ": " + specStr);
1391 }
1392 checkHasCoprocessor(className);
1393 return addCoprocessorToMap(specStr);
1394 }
1395
1396 private void checkHasCoprocessor(final String className) throws IOException {
1397 if (hasCoprocessor(className)) {
1398 throw new IOException("Coprocessor " + className + " already exists.");
1399 }
1400 }
1401
1402
1403
1404
1405
1406
1407
1408 private HTableDescriptor addCoprocessorToMap(final String specStr) {
1409 if (specStr == null) return this;
1410
1411 int maxCoprocessorNumber = 0;
1412 Matcher keyMatcher;
1413 for (Map.Entry<ImmutableBytesWritable, ImmutableBytesWritable> e:
1414 this.values.entrySet()) {
1415 keyMatcher =
1416 HConstants.CP_HTD_ATTR_KEY_PATTERN.matcher(
1417 Bytes.toString(e.getKey().get()));
1418 if (!keyMatcher.matches()) {
1419 continue;
1420 }
1421 maxCoprocessorNumber = Math.max(Integer.parseInt(keyMatcher.group(1)), maxCoprocessorNumber);
1422 }
1423 maxCoprocessorNumber++;
1424 String key = "coprocessor$" + Integer.toString(maxCoprocessorNumber);
1425 this.values.put(new ImmutableBytesWritable(Bytes.toBytes(key)),
1426 new ImmutableBytesWritable(Bytes.toBytes(specStr)));
1427 return this;
1428 }
1429
1430
1431
1432
1433
1434
1435
1436 public boolean hasCoprocessor(String classNameToMatch) {
1437 Matcher keyMatcher;
1438 Matcher valueMatcher;
1439 for (Map.Entry<ImmutableBytesWritable, ImmutableBytesWritable> e:
1440 this.values.entrySet()) {
1441 keyMatcher =
1442 HConstants.CP_HTD_ATTR_KEY_PATTERN.matcher(
1443 Bytes.toString(e.getKey().get()));
1444 if (!keyMatcher.matches()) {
1445 continue;
1446 }
1447 String className = getCoprocessorClassNameFromSpecStr(Bytes.toString(e.getValue().get()));
1448 if (className == null) continue;
1449 if (className.equals(classNameToMatch.trim())) {
1450 return true;
1451 }
1452 }
1453 return false;
1454 }
1455
1456
1457
1458
1459
1460
1461 public List<String> getCoprocessors() {
1462 List<String> result = new ArrayList<String>();
1463 Matcher keyMatcher;
1464 Matcher valueMatcher;
1465 for (Map.Entry<ImmutableBytesWritable, ImmutableBytesWritable> e : this.values.entrySet()) {
1466 keyMatcher = HConstants.CP_HTD_ATTR_KEY_PATTERN.matcher(Bytes.toString(e.getKey().get()));
1467 if (!keyMatcher.matches()) {
1468 continue;
1469 }
1470 String className = getCoprocessorClassNameFromSpecStr(Bytes.toString(e.getValue().get()));
1471 if (className == null) continue;
1472 result.add(className);
1473 }
1474 return result;
1475 }
1476
1477
1478
1479
1480
1481 private static String getCoprocessorClassNameFromSpecStr(final String spec) {
1482 Matcher matcher = HConstants.CP_HTD_ATTR_VALUE_PATTERN.matcher(spec);
1483
1484 return matcher != null && matcher.matches()? matcher.group(2).trim(): null;
1485 }
1486
1487
1488
1489
1490
1491 public void removeCoprocessor(String className) {
1492 ImmutableBytesWritable match = null;
1493 Matcher keyMatcher;
1494 Matcher valueMatcher;
1495 for (Map.Entry<ImmutableBytesWritable, ImmutableBytesWritable> e : this.values
1496 .entrySet()) {
1497 keyMatcher = HConstants.CP_HTD_ATTR_KEY_PATTERN.matcher(Bytes.toString(e
1498 .getKey().get()));
1499 if (!keyMatcher.matches()) {
1500 continue;
1501 }
1502 valueMatcher = HConstants.CP_HTD_ATTR_VALUE_PATTERN.matcher(Bytes
1503 .toString(e.getValue().get()));
1504 if (!valueMatcher.matches()) {
1505 continue;
1506 }
1507
1508 String clazz = valueMatcher.group(2).trim();
1509
1510 if (clazz.equals(className.trim())) {
1511 match = e.getKey();
1512 break;
1513 }
1514 }
1515
1516 if (match != null)
1517 remove(match);
1518 }
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530 @Deprecated
1531 public static Path getTableDir(Path rootdir, final byte [] tableName) {
1532
1533
1534 TableName name = TableName.valueOf(tableName);
1535 return new Path(rootdir, new Path(HConstants.BASE_NAMESPACE_DIR,
1536 new Path(name.getNamespaceAsString(), new Path(name.getQualifierAsString()))));
1537 }
1538
1539
1540
1541
1542
1543
1544 @Deprecated
1545 public static final HTableDescriptor META_TABLEDESC = new HTableDescriptor(
1546 TableName.META_TABLE_NAME,
1547 new HColumnDescriptor[] {
1548 new HColumnDescriptor(HConstants.CATALOG_FAMILY)
1549
1550 .setMaxVersions(HConstants.DEFAULT_HBASE_META_VERSIONS)
1551 .setInMemory(true)
1552 .setBlocksize(HConstants.DEFAULT_HBASE_META_BLOCK_SIZE)
1553 .setScope(HConstants.REPLICATION_SCOPE_LOCAL)
1554
1555 .setBloomFilterType(BloomType.NONE)
1556
1557
1558 .setCacheDataInL1(true)
1559 });
1560
1561 static {
1562 try {
1563 META_TABLEDESC.addCoprocessor(
1564 "org.apache.hadoop.hbase.coprocessor.MultiRowMutationEndpoint",
1565 null, Coprocessor.PRIORITY_SYSTEM, null);
1566 } catch (IOException ex) {
1567
1568 throw new RuntimeException(ex);
1569 }
1570 }
1571
1572 public final static String NAMESPACE_FAMILY_INFO = "info";
1573 public final static byte[] NAMESPACE_FAMILY_INFO_BYTES = Bytes.toBytes(NAMESPACE_FAMILY_INFO);
1574 public final static byte[] NAMESPACE_COL_DESC_BYTES = Bytes.toBytes("d");
1575
1576
1577 public static final HTableDescriptor NAMESPACE_TABLEDESC = new HTableDescriptor(
1578 TableName.NAMESPACE_TABLE_NAME,
1579 new HColumnDescriptor[] {
1580 new HColumnDescriptor(NAMESPACE_FAMILY_INFO)
1581
1582 .setMaxVersions(10)
1583 .setInMemory(true)
1584 .setBlocksize(8 * 1024)
1585 .setScope(HConstants.REPLICATION_SCOPE_LOCAL)
1586
1587
1588 .setCacheDataInL1(true)
1589 });
1590
1591 @Deprecated
1592 public void setOwner(User owner) {
1593 setOwnerString(owner != null ? owner.getShortName() : null);
1594 }
1595
1596
1597 @Deprecated
1598 public void setOwnerString(String ownerString) {
1599 if (ownerString != null) {
1600 setValue(OWNER_KEY, ownerString);
1601 } else {
1602 remove(OWNER_KEY);
1603 }
1604 }
1605
1606 @Deprecated
1607 public String getOwnerString() {
1608 if (getValue(OWNER_KEY) != null) {
1609 return Bytes.toString(getValue(OWNER_KEY));
1610 }
1611
1612
1613
1614 return null;
1615 }
1616
1617
1618
1619
1620
1621 public byte [] toByteArray() {
1622 return ProtobufUtil.prependPBMagic(convert().toByteArray());
1623 }
1624
1625
1626
1627
1628
1629
1630
1631
1632 public static HTableDescriptor parseFrom(final byte [] bytes)
1633 throws DeserializationException, IOException {
1634 if (!ProtobufUtil.isPBMagicPrefix(bytes)) {
1635 return (HTableDescriptor)Writables.getWritable(bytes, new HTableDescriptor());
1636 }
1637 int pblen = ProtobufUtil.lengthOfPBMagic();
1638 TableSchema.Builder builder = TableSchema.newBuilder();
1639 TableSchema ts;
1640 try {
1641 ProtobufUtil.mergeFrom(builder, bytes, pblen, bytes.length - pblen);
1642 ts = builder.build();
1643 } catch (IOException e) {
1644 throw new DeserializationException(e);
1645 }
1646 return convert(ts);
1647 }
1648
1649
1650
1651
1652 public TableSchema convert() {
1653 TableSchema.Builder builder = TableSchema.newBuilder();
1654 builder.setTableName(ProtobufUtil.toProtoTableName(getTableName()));
1655 for (Map.Entry<ImmutableBytesWritable, ImmutableBytesWritable> e: this.values.entrySet()) {
1656 BytesBytesPair.Builder aBuilder = BytesBytesPair.newBuilder();
1657 aBuilder.setFirst(ByteStringer.wrap(e.getKey().get()));
1658 aBuilder.setSecond(ByteStringer.wrap(e.getValue().get()));
1659 builder.addAttributes(aBuilder.build());
1660 }
1661 for (HColumnDescriptor hcd: getColumnFamilies()) {
1662 builder.addColumnFamilies(hcd.convert());
1663 }
1664 for (Map.Entry<String, String> e : this.configuration.entrySet()) {
1665 NameStringPair.Builder aBuilder = NameStringPair.newBuilder();
1666 aBuilder.setName(e.getKey());
1667 aBuilder.setValue(e.getValue());
1668 builder.addConfiguration(aBuilder.build());
1669 }
1670 return builder.build();
1671 }
1672
1673
1674
1675
1676
1677 public static HTableDescriptor convert(final TableSchema ts) {
1678 List<ColumnFamilySchema> list = ts.getColumnFamiliesList();
1679 HColumnDescriptor [] hcds = new HColumnDescriptor[list.size()];
1680 int index = 0;
1681 for (ColumnFamilySchema cfs: list) {
1682 hcds[index++] = HColumnDescriptor.convert(cfs);
1683 }
1684 HTableDescriptor htd = new HTableDescriptor(
1685 ProtobufUtil.toTableName(ts.getTableName()),
1686 hcds);
1687 for (BytesBytesPair a: ts.getAttributesList()) {
1688 htd.setValue(a.getFirst().toByteArray(), a.getSecond().toByteArray());
1689 }
1690 for (NameStringPair a: ts.getConfigurationList()) {
1691 htd.setConfiguration(a.getName(), a.getValue());
1692 }
1693 return htd;
1694 }
1695
1696
1697
1698
1699 public String getConfigurationValue(String key) {
1700 return configuration.get(key);
1701 }
1702
1703
1704
1705
1706 public Map<String, String> getConfiguration() {
1707
1708 return Collections.unmodifiableMap(configuration);
1709 }
1710
1711
1712
1713
1714
1715
1716 public void setConfiguration(String key, String value) {
1717 if (value == null) {
1718 removeConfiguration(key);
1719 } else {
1720 configuration.put(key, value);
1721 }
1722 }
1723
1724
1725
1726
1727 public void removeConfiguration(final String key) {
1728 configuration.remove(key);
1729 }
1730
1731 public static HTableDescriptor metaTableDescriptor(final Configuration conf)
1732 throws IOException {
1733 HTableDescriptor metaDescriptor = new HTableDescriptor(
1734 TableName.META_TABLE_NAME,
1735 new HColumnDescriptor[] {
1736 new HColumnDescriptor(HConstants.CATALOG_FAMILY)
1737 .setMaxVersions(conf.getInt(HConstants.HBASE_META_VERSIONS,
1738 HConstants.DEFAULT_HBASE_META_VERSIONS))
1739 .setInMemory(true)
1740 .setBlocksize(conf.getInt(HConstants.HBASE_META_BLOCK_SIZE,
1741 HConstants.DEFAULT_HBASE_META_BLOCK_SIZE))
1742 .setScope(HConstants.REPLICATION_SCOPE_LOCAL)
1743
1744 .setBloomFilterType(BloomType.NONE)
1745 });
1746 metaDescriptor.addCoprocessor(
1747 "org.apache.hadoop.hbase.coprocessor.MultiRowMutationEndpoint",
1748 null, Coprocessor.PRIORITY_SYSTEM, null);
1749 return metaDescriptor;
1750 }
1751
1752 }