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