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
839
840
841 public String toStringTableAttributes() {
842 return getValues(true).toString();
843 }
844
845 private StringBuilder getValues(boolean printDefaults) {
846 StringBuilder s = new StringBuilder();
847
848
849 Set<ImmutableBytesWritable> reservedKeys = new TreeSet<ImmutableBytesWritable>();
850 Set<ImmutableBytesWritable> userKeys = new TreeSet<ImmutableBytesWritable>();
851 for (ImmutableBytesWritable k : values.keySet()) {
852 if (k == null || k.get() == null) continue;
853 String key = Bytes.toString(k.get());
854
855 if (!RESERVED_KEYWORDS.contains(k) && !key.startsWith("coprocessor$")) {
856 userKeys.add(k);
857 continue;
858 }
859
860 String value = Bytes.toString(values.get(k).get());
861 if (key.equalsIgnoreCase(IS_ROOT) || key.equalsIgnoreCase(IS_META)) {
862 if (Boolean.valueOf(value) == false) continue;
863 }
864
865 if (printDefaults
866 || !DEFAULT_VALUES.containsKey(key)
867 || !DEFAULT_VALUES.get(key).equalsIgnoreCase(value)) {
868 reservedKeys.add(k);
869 }
870 }
871
872
873 boolean hasAttributes = !reservedKeys.isEmpty() || !userKeys.isEmpty();
874 if (!hasAttributes && configuration.isEmpty()) return s;
875
876 s.append(", {");
877
878 if (hasAttributes) {
879 s.append("TABLE_ATTRIBUTES => {");
880
881
882 boolean printCommaForAttr = false;
883 for (ImmutableBytesWritable k : reservedKeys) {
884 String key = Bytes.toString(k.get());
885 String value = Bytes.toStringBinary(values.get(k).get());
886 if (printCommaForAttr) s.append(", ");
887 printCommaForAttr = true;
888 s.append(key);
889 s.append(" => ");
890 s.append('\'').append(value).append('\'');
891 }
892
893 if (!userKeys.isEmpty()) {
894
895 if (printCommaForAttr) s.append(", ");
896 printCommaForAttr = true;
897 s.append(HConstants.METADATA).append(" => ");
898 s.append("{");
899 boolean printCommaForCfg = false;
900 for (ImmutableBytesWritable k : userKeys) {
901 String key = Bytes.toString(k.get());
902 String value = Bytes.toStringBinary(values.get(k).get());
903 if (printCommaForCfg) s.append(", ");
904 printCommaForCfg = true;
905 s.append('\'').append(key).append('\'');
906 s.append(" => ");
907 s.append('\'').append(value).append('\'');
908 }
909 s.append("}");
910 }
911 }
912
913
914 if (!configuration.isEmpty()) {
915 if (hasAttributes) {
916 s.append(", ");
917 }
918 s.append(HConstants.CONFIGURATION).append(" => ");
919 s.append('{');
920 boolean printCommaForConfig = false;
921 for (Map.Entry<String, String> e : configuration.entrySet()) {
922 if (printCommaForConfig) s.append(", ");
923 printCommaForConfig = true;
924 s.append('\'').append(e.getKey()).append('\'');
925 s.append(" => ");
926 s.append('\'').append(e.getValue()).append('\'');
927 }
928 s.append("}");
929 }
930 s.append("}");
931 return s;
932 }
933
934
935
936
937
938
939
940
941
942
943 @Override
944 public boolean equals(Object obj) {
945 if (this == obj) {
946 return true;
947 }
948 if (obj == null) {
949 return false;
950 }
951 if (!(obj instanceof HTableDescriptor)) {
952 return false;
953 }
954 return compareTo((HTableDescriptor)obj) == 0;
955 }
956
957
958
959
960 @Override
961 public int hashCode() {
962 int result = this.name.hashCode();
963 result ^= Byte.valueOf(TABLE_DESCRIPTOR_VERSION).hashCode();
964 if (this.families != null && this.families.size() > 0) {
965 for (HColumnDescriptor e: this.families.values()) {
966 result ^= e.hashCode();
967 }
968 }
969 result ^= values.hashCode();
970 result ^= configuration.hashCode();
971 return result;
972 }
973
974
975
976
977
978
979 @Deprecated
980 @Override
981 public void readFields(DataInput in) throws IOException {
982 int version = in.readInt();
983 if (version < 3)
984 throw new IOException("versions < 3 are not supported (and never existed!?)");
985
986 name = TableName.valueOf(Bytes.readByteArray(in));
987 setRootRegion(in.readBoolean());
988 setMetaRegion(in.readBoolean());
989 values.clear();
990 configuration.clear();
991 int numVals = in.readInt();
992 for (int i = 0; i < numVals; i++) {
993 ImmutableBytesWritable key = new ImmutableBytesWritable();
994 ImmutableBytesWritable value = new ImmutableBytesWritable();
995 key.readFields(in);
996 value.readFields(in);
997 setValue(key, value);
998 }
999 families.clear();
1000 int numFamilies = in.readInt();
1001 for (int i = 0; i < numFamilies; i++) {
1002 HColumnDescriptor c = new HColumnDescriptor();
1003 c.readFields(in);
1004 families.put(c.getName(), c);
1005 }
1006 if (version >= 7) {
1007 int numConfigs = in.readInt();
1008 for (int i = 0; i < numConfigs; i++) {
1009 ImmutableBytesWritable key = new ImmutableBytesWritable();
1010 ImmutableBytesWritable value = new ImmutableBytesWritable();
1011 key.readFields(in);
1012 value.readFields(in);
1013 configuration.put(
1014 Bytes.toString(key.get(), key.getOffset(), key.getLength()),
1015 Bytes.toString(value.get(), value.getOffset(), value.getLength()));
1016 }
1017 }
1018 }
1019
1020
1021
1022
1023
1024
1025
1026 @Deprecated
1027 @Override
1028 public void write(DataOutput out) throws IOException {
1029 out.writeInt(TABLE_DESCRIPTOR_VERSION);
1030 Bytes.writeByteArray(out, name.toBytes());
1031 out.writeBoolean(isRootRegion());
1032 out.writeBoolean(isMetaRegion());
1033 out.writeInt(values.size());
1034 for (Map.Entry<ImmutableBytesWritable, ImmutableBytesWritable> e:
1035 values.entrySet()) {
1036 e.getKey().write(out);
1037 e.getValue().write(out);
1038 }
1039 out.writeInt(families.size());
1040 for(Iterator<HColumnDescriptor> it = families.values().iterator();
1041 it.hasNext(); ) {
1042 HColumnDescriptor family = it.next();
1043 family.write(out);
1044 }
1045 out.writeInt(configuration.size());
1046 for (Map.Entry<String, String> e : configuration.entrySet()) {
1047 new ImmutableBytesWritable(Bytes.toBytes(e.getKey())).write(out);
1048 new ImmutableBytesWritable(Bytes.toBytes(e.getValue())).write(out);
1049 }
1050 }
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061 @Override
1062 public int compareTo(final HTableDescriptor other) {
1063 int result = this.name.compareTo(other.name);
1064 if (result == 0) {
1065 result = families.size() - other.families.size();
1066 }
1067 if (result == 0 && families.size() != other.families.size()) {
1068 result = Integer.valueOf(families.size()).compareTo(
1069 Integer.valueOf(other.families.size()));
1070 }
1071 if (result == 0) {
1072 for (Iterator<HColumnDescriptor> it = families.values().iterator(),
1073 it2 = other.families.values().iterator(); it.hasNext(); ) {
1074 result = it.next().compareTo(it2.next());
1075 if (result != 0) {
1076 break;
1077 }
1078 }
1079 }
1080 if (result == 0) {
1081
1082 result = this.values.hashCode() - other.values.hashCode();
1083 if (result < 0)
1084 result = -1;
1085 else if (result > 0)
1086 result = 1;
1087 }
1088 if (result == 0) {
1089 result = this.configuration.hashCode() - other.configuration.hashCode();
1090 if (result < 0)
1091 result = -1;
1092 else if (result > 0)
1093 result = 1;
1094 }
1095 return result;
1096 }
1097
1098
1099
1100
1101
1102
1103
1104
1105 public Collection<HColumnDescriptor> getFamilies() {
1106 return Collections.unmodifiableCollection(this.families.values());
1107 }
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117 public Set<byte[]> getFamiliesKeys() {
1118 return Collections.unmodifiableSet(this.families.keySet());
1119 }
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129 public HColumnDescriptor[] getColumnFamilies() {
1130 Collection<HColumnDescriptor> hColumnDescriptors = getFamilies();
1131 return hColumnDescriptors.toArray(new HColumnDescriptor[hColumnDescriptors.size()]);
1132 }
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143 public HColumnDescriptor getFamily(final byte [] column) {
1144 return this.families.get(column);
1145 }
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156 public HColumnDescriptor removeFamily(final byte [] column) {
1157 return this.families.remove(column);
1158 }
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171 public void addCoprocessor(String className) throws IOException {
1172 addCoprocessor(className, null, Coprocessor.PRIORITY_USER, null);
1173 }
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190 public void addCoprocessor(String className, Path jarFilePath,
1191 int priority, final Map<String, String> kvs)
1192 throws IOException {
1193 if (hasCoprocessor(className)) {
1194 throw new IOException("Coprocessor " + className + " already exists.");
1195 }
1196
1197 StringBuilder kvString = new StringBuilder();
1198 if (kvs != null) {
1199 for (Map.Entry<String, String> e: kvs.entrySet()) {
1200 if (!e.getKey().matches(HConstants.CP_HTD_ATTR_VALUE_PARAM_KEY_PATTERN)) {
1201 throw new IOException("Illegal parameter key = " + e.getKey());
1202 }
1203 if (!e.getValue().matches(HConstants.CP_HTD_ATTR_VALUE_PARAM_VALUE_PATTERN)) {
1204 throw new IOException("Illegal parameter (" + e.getKey() +
1205 ") value = " + e.getValue());
1206 }
1207 if (kvString.length() != 0) {
1208 kvString.append(',');
1209 }
1210 kvString.append(e.getKey());
1211 kvString.append('=');
1212 kvString.append(e.getValue());
1213 }
1214 }
1215
1216
1217 int maxCoprocessorNumber = 0;
1218 Matcher keyMatcher;
1219 for (Map.Entry<ImmutableBytesWritable, ImmutableBytesWritable> e:
1220 this.values.entrySet()) {
1221 keyMatcher =
1222 HConstants.CP_HTD_ATTR_KEY_PATTERN.matcher(
1223 Bytes.toString(e.getKey().get()));
1224 if (!keyMatcher.matches()) {
1225 continue;
1226 }
1227 maxCoprocessorNumber = Math.max(Integer.parseInt(keyMatcher.group(1)),
1228 maxCoprocessorNumber);
1229 }
1230 maxCoprocessorNumber++;
1231
1232 String key = "coprocessor$" + Integer.toString(maxCoprocessorNumber);
1233 String value = ((jarFilePath == null)? "" : jarFilePath.toString()) +
1234 "|" + className + "|" + Integer.toString(priority) + "|" +
1235 kvString.toString();
1236 setValue(key, value);
1237 }
1238
1239
1240
1241
1242
1243
1244
1245
1246 public boolean hasCoprocessor(String className) {
1247 Matcher keyMatcher;
1248 Matcher valueMatcher;
1249 for (Map.Entry<ImmutableBytesWritable, ImmutableBytesWritable> e:
1250 this.values.entrySet()) {
1251 keyMatcher =
1252 HConstants.CP_HTD_ATTR_KEY_PATTERN.matcher(
1253 Bytes.toString(e.getKey().get()));
1254 if (!keyMatcher.matches()) {
1255 continue;
1256 }
1257 valueMatcher =
1258 HConstants.CP_HTD_ATTR_VALUE_PATTERN.matcher(
1259 Bytes.toString(e.getValue().get()));
1260 if (!valueMatcher.matches()) {
1261 continue;
1262 }
1263
1264 String clazz = valueMatcher.group(2).trim();
1265 if (clazz.equals(className.trim())) {
1266 return true;
1267 }
1268 }
1269 return false;
1270 }
1271
1272
1273
1274
1275
1276
1277 public List<String> getCoprocessors() {
1278 List<String> result = new ArrayList<String>();
1279 Matcher keyMatcher;
1280 Matcher valueMatcher;
1281 for (Map.Entry<ImmutableBytesWritable, ImmutableBytesWritable> e : this.values.entrySet()) {
1282 keyMatcher = HConstants.CP_HTD_ATTR_KEY_PATTERN.matcher(Bytes.toString(e.getKey().get()));
1283 if (!keyMatcher.matches()) {
1284 continue;
1285 }
1286 valueMatcher = HConstants.CP_HTD_ATTR_VALUE_PATTERN.matcher(Bytes
1287 .toString(e.getValue().get()));
1288 if (!valueMatcher.matches()) {
1289 continue;
1290 }
1291 result.add(valueMatcher.group(2).trim());
1292 }
1293 return result;
1294 }
1295
1296
1297
1298
1299
1300 public void removeCoprocessor(String className) {
1301 ImmutableBytesWritable match = null;
1302 Matcher keyMatcher;
1303 Matcher valueMatcher;
1304 for (Map.Entry<ImmutableBytesWritable, ImmutableBytesWritable> e : this.values
1305 .entrySet()) {
1306 keyMatcher = HConstants.CP_HTD_ATTR_KEY_PATTERN.matcher(Bytes.toString(e
1307 .getKey().get()));
1308 if (!keyMatcher.matches()) {
1309 continue;
1310 }
1311 valueMatcher = HConstants.CP_HTD_ATTR_VALUE_PATTERN.matcher(Bytes
1312 .toString(e.getValue().get()));
1313 if (!valueMatcher.matches()) {
1314 continue;
1315 }
1316
1317 String clazz = valueMatcher.group(2).trim();
1318
1319 if (clazz.equals(className.trim())) {
1320 match = e.getKey();
1321 break;
1322 }
1323 }
1324
1325 if (match != null)
1326 remove(match);
1327 }
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339 @Deprecated
1340 public static Path getTableDir(Path rootdir, final byte [] tableName) {
1341
1342
1343 TableName name = TableName.valueOf(tableName);
1344 return new Path(rootdir, new Path(HConstants.BASE_NAMESPACE_DIR,
1345 new Path(name.getNamespaceAsString(), new Path(name.getQualifierAsString()))));
1346 }
1347
1348
1349
1350
1351
1352
1353 @Deprecated
1354 public static final HTableDescriptor META_TABLEDESC = new HTableDescriptor(
1355 TableName.META_TABLE_NAME,
1356 new HColumnDescriptor[] {
1357 new HColumnDescriptor(HConstants.CATALOG_FAMILY)
1358
1359 .setMaxVersions(HConstants.DEFAULT_HBASE_META_VERSIONS)
1360 .setInMemory(true)
1361 .setBlocksize(HConstants.DEFAULT_HBASE_META_BLOCK_SIZE)
1362 .setScope(HConstants.REPLICATION_SCOPE_LOCAL)
1363
1364 .setBloomFilterType(BloomType.NONE)
1365 });
1366
1367 static {
1368 try {
1369 META_TABLEDESC.addCoprocessor(
1370 "org.apache.hadoop.hbase.coprocessor.MultiRowMutationEndpoint",
1371 null, Coprocessor.PRIORITY_SYSTEM, null);
1372 } catch (IOException ex) {
1373
1374 throw new RuntimeException(ex);
1375 }
1376 }
1377
1378 public final static String NAMESPACE_FAMILY_INFO = "info";
1379 public final static byte[] NAMESPACE_FAMILY_INFO_BYTES = Bytes.toBytes(NAMESPACE_FAMILY_INFO);
1380 public final static byte[] NAMESPACE_COL_DESC_BYTES = Bytes.toBytes("d");
1381
1382
1383 public static final HTableDescriptor NAMESPACE_TABLEDESC = new HTableDescriptor(
1384 TableName.NAMESPACE_TABLE_NAME,
1385 new HColumnDescriptor[] {
1386 new HColumnDescriptor(NAMESPACE_FAMILY_INFO)
1387
1388 .setMaxVersions(10)
1389 .setInMemory(true)
1390 .setBlocksize(8 * 1024)
1391 .setScope(HConstants.REPLICATION_SCOPE_LOCAL)
1392 });
1393
1394 @Deprecated
1395 public void setOwner(User owner) {
1396 setOwnerString(owner != null ? owner.getShortName() : null);
1397 }
1398
1399
1400 @Deprecated
1401 public void setOwnerString(String ownerString) {
1402 if (ownerString != null) {
1403 setValue(OWNER_KEY, ownerString);
1404 } else {
1405 remove(OWNER_KEY);
1406 }
1407 }
1408
1409 @Deprecated
1410 public String getOwnerString() {
1411 if (getValue(OWNER_KEY) != null) {
1412 return Bytes.toString(getValue(OWNER_KEY));
1413 }
1414
1415
1416
1417 return null;
1418 }
1419
1420
1421
1422
1423
1424 public byte [] toByteArray() {
1425 return ProtobufUtil.prependPBMagic(convert().toByteArray());
1426 }
1427
1428
1429
1430
1431
1432
1433
1434
1435 public static HTableDescriptor parseFrom(final byte [] bytes)
1436 throws DeserializationException, IOException {
1437 if (!ProtobufUtil.isPBMagicPrefix(bytes)) {
1438 return (HTableDescriptor)Writables.getWritable(bytes, new HTableDescriptor());
1439 }
1440 int pblen = ProtobufUtil.lengthOfPBMagic();
1441 TableSchema.Builder builder = TableSchema.newBuilder();
1442 TableSchema ts;
1443 try {
1444 ts = builder.mergeFrom(bytes, pblen, bytes.length - pblen).build();
1445 } catch (InvalidProtocolBufferException e) {
1446 throw new DeserializationException(e);
1447 }
1448 return convert(ts);
1449 }
1450
1451
1452
1453
1454 public TableSchema convert() {
1455 TableSchema.Builder builder = TableSchema.newBuilder();
1456 builder.setTableName(ProtobufUtil.toProtoTableName(getTableName()));
1457 for (Map.Entry<ImmutableBytesWritable, ImmutableBytesWritable> e: this.values.entrySet()) {
1458 BytesBytesPair.Builder aBuilder = BytesBytesPair.newBuilder();
1459 aBuilder.setFirst(ByteStringer.wrap(e.getKey().get()));
1460 aBuilder.setSecond(ByteStringer.wrap(e.getValue().get()));
1461 builder.addAttributes(aBuilder.build());
1462 }
1463 for (HColumnDescriptor hcd: getColumnFamilies()) {
1464 builder.addColumnFamilies(hcd.convert());
1465 }
1466 for (Map.Entry<String, String> e : this.configuration.entrySet()) {
1467 NameStringPair.Builder aBuilder = NameStringPair.newBuilder();
1468 aBuilder.setName(e.getKey());
1469 aBuilder.setValue(e.getValue());
1470 builder.addConfiguration(aBuilder.build());
1471 }
1472 return builder.build();
1473 }
1474
1475
1476
1477
1478
1479 public static HTableDescriptor convert(final TableSchema ts) {
1480 List<ColumnFamilySchema> list = ts.getColumnFamiliesList();
1481 HColumnDescriptor [] hcds = new HColumnDescriptor[list.size()];
1482 int index = 0;
1483 for (ColumnFamilySchema cfs: list) {
1484 hcds[index++] = HColumnDescriptor.convert(cfs);
1485 }
1486 HTableDescriptor htd = new HTableDescriptor(
1487 ProtobufUtil.toTableName(ts.getTableName()),
1488 hcds);
1489 for (BytesBytesPair a: ts.getAttributesList()) {
1490 htd.setValue(a.getFirst().toByteArray(), a.getSecond().toByteArray());
1491 }
1492 for (NameStringPair a: ts.getConfigurationList()) {
1493 htd.setConfiguration(a.getName(), a.getValue());
1494 }
1495 return htd;
1496 }
1497
1498
1499
1500
1501 public String getConfigurationValue(String key) {
1502 return configuration.get(key);
1503 }
1504
1505
1506
1507
1508 public Map<String, String> getConfiguration() {
1509
1510 return Collections.unmodifiableMap(configuration);
1511 }
1512
1513
1514
1515
1516
1517
1518 public void setConfiguration(String key, String value) {
1519 if (value == null) {
1520 removeConfiguration(key);
1521 } else {
1522 configuration.put(key, value);
1523 }
1524 }
1525
1526
1527
1528
1529 public void removeConfiguration(final String key) {
1530 configuration.remove(key);
1531 }
1532
1533 public static HTableDescriptor metaTableDescriptor(final Configuration conf)
1534 throws IOException {
1535 HTableDescriptor metaDescriptor = new HTableDescriptor(
1536 TableName.META_TABLE_NAME,
1537 new HColumnDescriptor[] {
1538 new HColumnDescriptor(HConstants.CATALOG_FAMILY)
1539 .setMaxVersions(conf.getInt(HConstants.HBASE_META_VERSIONS,
1540 HConstants.DEFAULT_HBASE_META_VERSIONS))
1541 .setInMemory(true)
1542 .setBlocksize(conf.getInt(HConstants.HBASE_META_BLOCK_SIZE,
1543 HConstants.DEFAULT_HBASE_META_BLOCK_SIZE))
1544 .setScope(HConstants.REPLICATION_SCOPE_LOCAL)
1545
1546 .setBloomFilterType(BloomType.NONE)
1547 });
1548 metaDescriptor.addCoprocessor(
1549 "org.apache.hadoop.hbase.coprocessor.MultiRowMutationEndpoint",
1550 null, Coprocessor.PRIORITY_SYSTEM, null);
1551 return metaDescriptor;
1552 }
1553
1554 }