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 public void addCoprocessor(String className) throws IOException {
1168 addCoprocessor(className, null, Coprocessor.PRIORITY_USER, null);
1169 }
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185 public void addCoprocessor(String className, Path jarFilePath,
1186 int priority, final Map<String, String> kvs)
1187 throws IOException {
1188 checkHasCoprocessor(className);
1189
1190
1191 StringBuilder kvString = new StringBuilder();
1192 if (kvs != null) {
1193 for (Map.Entry<String, String> e: kvs.entrySet()) {
1194 if (!e.getKey().matches(HConstants.CP_HTD_ATTR_VALUE_PARAM_KEY_PATTERN)) {
1195 throw new IOException("Illegal parameter key = " + e.getKey());
1196 }
1197 if (!e.getValue().matches(HConstants.CP_HTD_ATTR_VALUE_PARAM_VALUE_PATTERN)) {
1198 throw new IOException("Illegal parameter (" + e.getKey() +
1199 ") value = " + e.getValue());
1200 }
1201 if (kvString.length() != 0) {
1202 kvString.append(',');
1203 }
1204 kvString.append(e.getKey());
1205 kvString.append('=');
1206 kvString.append(e.getValue());
1207 }
1208 }
1209
1210 String value = ((jarFilePath == null)? "" : jarFilePath.toString()) +
1211 "|" + className + "|" + Integer.toString(priority) + "|" +
1212 kvString.toString();
1213 addCoprocessorToMap(value);
1214 }
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227 public HTableDescriptor addCoprocessorWithSpec(final String specStr) throws IOException {
1228 String className = getCoprocessorClassNameFromSpecStr(specStr);
1229 if (className == null) {
1230 throw new IllegalArgumentException("Format does not match " +
1231 HConstants.CP_HTD_ATTR_VALUE_PATTERN + ": " + specStr);
1232 }
1233 checkHasCoprocessor(className);
1234 return addCoprocessorToMap(specStr);
1235 }
1236
1237 private void checkHasCoprocessor(final String className) throws IOException {
1238 if (hasCoprocessor(className)) {
1239 throw new IOException("Coprocessor " + className + " already exists.");
1240 }
1241 }
1242
1243
1244
1245
1246
1247
1248
1249 private HTableDescriptor addCoprocessorToMap(final String specStr) {
1250 if (specStr == null) return this;
1251
1252 int maxCoprocessorNumber = 0;
1253 Matcher keyMatcher;
1254 for (Map.Entry<ImmutableBytesWritable, ImmutableBytesWritable> e:
1255 this.values.entrySet()) {
1256 keyMatcher =
1257 HConstants.CP_HTD_ATTR_KEY_PATTERN.matcher(
1258 Bytes.toString(e.getKey().get()));
1259 if (!keyMatcher.matches()) {
1260 continue;
1261 }
1262 maxCoprocessorNumber = Math.max(Integer.parseInt(keyMatcher.group(1)), maxCoprocessorNumber);
1263 }
1264 maxCoprocessorNumber++;
1265 String key = "coprocessor$" + Integer.toString(maxCoprocessorNumber);
1266 this.values.put(new ImmutableBytesWritable(Bytes.toBytes(key)),
1267 new ImmutableBytesWritable(Bytes.toBytes(specStr)));
1268 return this;
1269 }
1270
1271
1272
1273
1274
1275
1276
1277 public boolean hasCoprocessor(String classNameToMatch) {
1278 Matcher keyMatcher;
1279 Matcher valueMatcher;
1280 for (Map.Entry<ImmutableBytesWritable, ImmutableBytesWritable> e:
1281 this.values.entrySet()) {
1282 keyMatcher =
1283 HConstants.CP_HTD_ATTR_KEY_PATTERN.matcher(
1284 Bytes.toString(e.getKey().get()));
1285 if (!keyMatcher.matches()) {
1286 continue;
1287 }
1288 String className = getCoprocessorClassNameFromSpecStr(Bytes.toString(e.getValue().get()));
1289 if (className == null) continue;
1290 if (className.equals(classNameToMatch.trim())) {
1291 return true;
1292 }
1293 }
1294 return false;
1295 }
1296
1297
1298
1299
1300
1301
1302 public List<String> getCoprocessors() {
1303 List<String> result = new ArrayList<String>();
1304 Matcher keyMatcher;
1305 Matcher valueMatcher;
1306 for (Map.Entry<ImmutableBytesWritable, ImmutableBytesWritable> e : this.values.entrySet()) {
1307 keyMatcher = HConstants.CP_HTD_ATTR_KEY_PATTERN.matcher(Bytes.toString(e.getKey().get()));
1308 if (!keyMatcher.matches()) {
1309 continue;
1310 }
1311 String className = getCoprocessorClassNameFromSpecStr(Bytes.toString(e.getValue().get()));
1312 if (className == null) continue;
1313 result.add(className);
1314 }
1315 return result;
1316 }
1317
1318
1319
1320
1321
1322 private static String getCoprocessorClassNameFromSpecStr(final String spec) {
1323 Matcher matcher = HConstants.CP_HTD_ATTR_VALUE_PATTERN.matcher(spec);
1324
1325 return matcher != null && matcher.matches()? matcher.group(2).trim(): null;
1326 }
1327
1328
1329
1330
1331
1332 public void removeCoprocessor(String className) {
1333 ImmutableBytesWritable match = null;
1334 Matcher keyMatcher;
1335 Matcher valueMatcher;
1336 for (Map.Entry<ImmutableBytesWritable, ImmutableBytesWritable> e : this.values
1337 .entrySet()) {
1338 keyMatcher = HConstants.CP_HTD_ATTR_KEY_PATTERN.matcher(Bytes.toString(e
1339 .getKey().get()));
1340 if (!keyMatcher.matches()) {
1341 continue;
1342 }
1343 valueMatcher = HConstants.CP_HTD_ATTR_VALUE_PATTERN.matcher(Bytes
1344 .toString(e.getValue().get()));
1345 if (!valueMatcher.matches()) {
1346 continue;
1347 }
1348
1349 String clazz = valueMatcher.group(2).trim();
1350
1351 if (clazz.equals(className.trim())) {
1352 match = e.getKey();
1353 break;
1354 }
1355 }
1356
1357 if (match != null)
1358 remove(match);
1359 }
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371 @Deprecated
1372 public static Path getTableDir(Path rootdir, final byte [] tableName) {
1373
1374
1375 TableName name = TableName.valueOf(tableName);
1376 return new Path(rootdir, new Path(HConstants.BASE_NAMESPACE_DIR,
1377 new Path(name.getNamespaceAsString(), new Path(name.getQualifierAsString()))));
1378 }
1379
1380
1381
1382
1383
1384
1385 @Deprecated
1386 public static final HTableDescriptor META_TABLEDESC = new HTableDescriptor(
1387 TableName.META_TABLE_NAME,
1388 new HColumnDescriptor[] {
1389 new HColumnDescriptor(HConstants.CATALOG_FAMILY)
1390
1391 .setMaxVersions(HConstants.DEFAULT_HBASE_META_VERSIONS)
1392 .setInMemory(true)
1393 .setBlocksize(HConstants.DEFAULT_HBASE_META_BLOCK_SIZE)
1394 .setScope(HConstants.REPLICATION_SCOPE_LOCAL)
1395
1396 .setBloomFilterType(BloomType.NONE)
1397 });
1398
1399 static {
1400 try {
1401 META_TABLEDESC.addCoprocessor(
1402 "org.apache.hadoop.hbase.coprocessor.MultiRowMutationEndpoint",
1403 null, Coprocessor.PRIORITY_SYSTEM, null);
1404 } catch (IOException ex) {
1405
1406 throw new RuntimeException(ex);
1407 }
1408 }
1409
1410 public final static String NAMESPACE_FAMILY_INFO = "info";
1411 public final static byte[] NAMESPACE_FAMILY_INFO_BYTES = Bytes.toBytes(NAMESPACE_FAMILY_INFO);
1412 public final static byte[] NAMESPACE_COL_DESC_BYTES = Bytes.toBytes("d");
1413
1414
1415 public static final HTableDescriptor NAMESPACE_TABLEDESC = new HTableDescriptor(
1416 TableName.NAMESPACE_TABLE_NAME,
1417 new HColumnDescriptor[] {
1418 new HColumnDescriptor(NAMESPACE_FAMILY_INFO)
1419
1420 .setMaxVersions(10)
1421 .setInMemory(true)
1422 .setBlocksize(8 * 1024)
1423 .setScope(HConstants.REPLICATION_SCOPE_LOCAL)
1424 });
1425
1426 @Deprecated
1427 public void setOwner(User owner) {
1428 setOwnerString(owner != null ? owner.getShortName() : null);
1429 }
1430
1431
1432 @Deprecated
1433 public void setOwnerString(String ownerString) {
1434 if (ownerString != null) {
1435 setValue(OWNER_KEY, ownerString);
1436 } else {
1437 remove(OWNER_KEY);
1438 }
1439 }
1440
1441 @Deprecated
1442 public String getOwnerString() {
1443 if (getValue(OWNER_KEY) != null) {
1444 return Bytes.toString(getValue(OWNER_KEY));
1445 }
1446
1447
1448
1449 return null;
1450 }
1451
1452
1453
1454
1455
1456 public byte [] toByteArray() {
1457 return ProtobufUtil.prependPBMagic(convert().toByteArray());
1458 }
1459
1460
1461
1462
1463
1464
1465
1466
1467 public static HTableDescriptor parseFrom(final byte [] bytes)
1468 throws DeserializationException, IOException {
1469 if (!ProtobufUtil.isPBMagicPrefix(bytes)) {
1470 return (HTableDescriptor)Writables.getWritable(bytes, new HTableDescriptor());
1471 }
1472 int pblen = ProtobufUtil.lengthOfPBMagic();
1473 TableSchema.Builder builder = TableSchema.newBuilder();
1474 TableSchema ts;
1475 try {
1476 ProtobufUtil.mergeFrom(builder, bytes, pblen, bytes.length - pblen);
1477 ts = builder.build();
1478 } catch (IOException e) {
1479 throw new DeserializationException(e);
1480 }
1481 return convert(ts);
1482 }
1483
1484
1485
1486
1487 public TableSchema convert() {
1488 TableSchema.Builder builder = TableSchema.newBuilder();
1489 builder.setTableName(ProtobufUtil.toProtoTableName(getTableName()));
1490 for (Map.Entry<ImmutableBytesWritable, ImmutableBytesWritable> e: this.values.entrySet()) {
1491 BytesBytesPair.Builder aBuilder = BytesBytesPair.newBuilder();
1492 aBuilder.setFirst(ByteStringer.wrap(e.getKey().get()));
1493 aBuilder.setSecond(ByteStringer.wrap(e.getValue().get()));
1494 builder.addAttributes(aBuilder.build());
1495 }
1496 for (HColumnDescriptor hcd: getColumnFamilies()) {
1497 builder.addColumnFamilies(hcd.convert());
1498 }
1499 for (Map.Entry<String, String> e : this.configuration.entrySet()) {
1500 NameStringPair.Builder aBuilder = NameStringPair.newBuilder();
1501 aBuilder.setName(e.getKey());
1502 aBuilder.setValue(e.getValue());
1503 builder.addConfiguration(aBuilder.build());
1504 }
1505 return builder.build();
1506 }
1507
1508
1509
1510
1511
1512 public static HTableDescriptor convert(final TableSchema ts) {
1513 List<ColumnFamilySchema> list = ts.getColumnFamiliesList();
1514 HColumnDescriptor [] hcds = new HColumnDescriptor[list.size()];
1515 int index = 0;
1516 for (ColumnFamilySchema cfs: list) {
1517 hcds[index++] = HColumnDescriptor.convert(cfs);
1518 }
1519 HTableDescriptor htd = new HTableDescriptor(
1520 ProtobufUtil.toTableName(ts.getTableName()),
1521 hcds);
1522 for (BytesBytesPair a: ts.getAttributesList()) {
1523 htd.setValue(a.getFirst().toByteArray(), a.getSecond().toByteArray());
1524 }
1525 for (NameStringPair a: ts.getConfigurationList()) {
1526 htd.setConfiguration(a.getName(), a.getValue());
1527 }
1528 return htd;
1529 }
1530
1531
1532
1533
1534 public String getConfigurationValue(String key) {
1535 return configuration.get(key);
1536 }
1537
1538
1539
1540
1541 public Map<String, String> getConfiguration() {
1542
1543 return Collections.unmodifiableMap(configuration);
1544 }
1545
1546
1547
1548
1549
1550
1551 public void setConfiguration(String key, String value) {
1552 if (value == null) {
1553 removeConfiguration(key);
1554 } else {
1555 configuration.put(key, value);
1556 }
1557 }
1558
1559
1560
1561
1562 public void removeConfiguration(final String key) {
1563 configuration.remove(key);
1564 }
1565
1566 public static HTableDescriptor metaTableDescriptor(final Configuration conf)
1567 throws IOException {
1568 HTableDescriptor metaDescriptor = new HTableDescriptor(
1569 TableName.META_TABLE_NAME,
1570 new HColumnDescriptor[] {
1571 new HColumnDescriptor(HConstants.CATALOG_FAMILY)
1572 .setMaxVersions(conf.getInt(HConstants.HBASE_META_VERSIONS,
1573 HConstants.DEFAULT_HBASE_META_VERSIONS))
1574 .setInMemory(true)
1575 .setBlocksize(conf.getInt(HConstants.HBASE_META_BLOCK_SIZE,
1576 HConstants.DEFAULT_HBASE_META_BLOCK_SIZE))
1577 .setScope(HConstants.REPLICATION_SCOPE_LOCAL)
1578
1579 .setBloomFilterType(BloomType.NONE)
1580 });
1581 metaDescriptor.addCoprocessor(
1582 "org.apache.hadoop.hbase.coprocessor.MultiRowMutationEndpoint",
1583 null, Coprocessor.PRIORITY_SYSTEM, null);
1584 return metaDescriptor;
1585 }
1586
1587 }