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