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