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