001/**
002 *
003 * Licensed to the Apache Software Foundation (ASF) under one
004 * or more contributor license agreements.  See the NOTICE file
005 * distributed with this work for additional information
006 * regarding copyright ownership.  The ASF licenses this file
007 * to you under the Apache License, Version 2.0 (the
008 * "License"); you may not use this file except in compliance
009 * with the License.  You may obtain a copy of the License at
010 *
011 *     http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing, software
014 * distributed under the License is distributed on an "AS IS" BASIS,
015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016 * See the License for the specific language governing permissions and
017 * limitations under the License.
018 */
019package org.apache.hadoop.hbase;
020
021import java.io.IOException;
022import java.util.Collection;
023import java.util.Collections;
024import java.util.Map;
025import java.util.Set;
026import java.util.stream.Collectors;
027import java.util.stream.Stream;
028import org.apache.hadoop.fs.Path;
029import org.apache.hadoop.hbase.client.ColumnFamilyDescriptor;
030import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder.ModifyableColumnFamilyDescriptor;
031import org.apache.hadoop.hbase.client.CoprocessorDescriptor;
032import org.apache.hadoop.hbase.client.CoprocessorDescriptorBuilder;
033import org.apache.hadoop.hbase.client.Durability;
034import org.apache.hadoop.hbase.client.TableDescriptor;
035import org.apache.hadoop.hbase.client.TableDescriptorBuilder;
036import org.apache.hadoop.hbase.client.TableDescriptorBuilder.ModifyableTableDescriptor;
037import org.apache.hadoop.hbase.exceptions.DeserializationException;
038import org.apache.hadoop.hbase.security.User;
039import org.apache.hadoop.hbase.util.Bytes;
040import org.apache.yetus.audience.InterfaceAudience;
041
042/**
043 * HTableDescriptor contains the details about an HBase table  such as the descriptors of
044 * all the column families, is the table a catalog table, <code> hbase:meta </code>,
045 * if the table is read only, the maximum size of the memstore,
046 * when the region split should occur, coprocessors associated with it etc...
047 * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0.
048 *             Use {@link TableDescriptorBuilder} to build {@link HTableDescriptor}.
049 */
050@Deprecated
051@InterfaceAudience.Public
052public class HTableDescriptor implements TableDescriptor, Comparable<HTableDescriptor> {
053  public static final String SPLIT_POLICY = TableDescriptorBuilder.SPLIT_POLICY;
054  public static final String MAX_FILESIZE = TableDescriptorBuilder.MAX_FILESIZE;
055  public static final String OWNER = TableDescriptorBuilder.OWNER;
056  public static final Bytes OWNER_KEY = TableDescriptorBuilder.OWNER_KEY;
057  public static final String READONLY = TableDescriptorBuilder.READONLY;
058  public static final String COMPACTION_ENABLED = TableDescriptorBuilder.COMPACTION_ENABLED;
059  public static final String SPLIT_ENABLED = TableDescriptorBuilder.SPLIT_ENABLED;
060  public static final String MERGE_ENABLED = TableDescriptorBuilder.MERGE_ENABLED;
061  public static final String MEMSTORE_FLUSHSIZE = TableDescriptorBuilder.MEMSTORE_FLUSHSIZE;
062  public static final String FLUSH_POLICY = TableDescriptorBuilder.FLUSH_POLICY;
063  public static final String IS_ROOT = "IS_ROOT";
064  public static final String IS_META = TableDescriptorBuilder.IS_META;
065  public static final String DURABILITY = TableDescriptorBuilder.DURABILITY;
066  public static final String REGION_REPLICATION = TableDescriptorBuilder.REGION_REPLICATION;
067  public static final String REGION_MEMSTORE_REPLICATION = TableDescriptorBuilder.REGION_MEMSTORE_REPLICATION;
068  public static final String NORMALIZATION_ENABLED = TableDescriptorBuilder.NORMALIZATION_ENABLED;
069  public static final String NORMALIZER_TARGET_REGION_COUNT =
070      TableDescriptorBuilder.NORMALIZER_TARGET_REGION_COUNT;
071  public static final String NORMALIZER_TARGET_REGION_SIZE =
072      TableDescriptorBuilder.NORMALIZER_TARGET_REGION_SIZE;
073  public static final String PRIORITY = TableDescriptorBuilder.PRIORITY;
074  public static final boolean DEFAULT_READONLY = TableDescriptorBuilder.DEFAULT_READONLY;
075  public static final boolean DEFAULT_COMPACTION_ENABLED = TableDescriptorBuilder.DEFAULT_COMPACTION_ENABLED;
076  public static final boolean DEFAULT_NORMALIZATION_ENABLED = TableDescriptorBuilder.DEFAULT_NORMALIZATION_ENABLED;
077  public static final long DEFAULT_MEMSTORE_FLUSH_SIZE = TableDescriptorBuilder.DEFAULT_MEMSTORE_FLUSH_SIZE;
078  public static final int DEFAULT_REGION_REPLICATION = TableDescriptorBuilder.DEFAULT_REGION_REPLICATION;
079  public static final boolean DEFAULT_REGION_MEMSTORE_REPLICATION = TableDescriptorBuilder.DEFAULT_REGION_MEMSTORE_REPLICATION;
080  protected final ModifyableTableDescriptor delegatee;
081
082  /**
083   * Construct a table descriptor specifying a TableName object
084   * @param name Table name.
085   * @see <a href="https://issues.apache.org/jira/browse/HBASE-174">HADOOP-1581 HBASE: (HBASE-174) Un-openable tablename bug</a>
086   */
087  public HTableDescriptor(final TableName name) {
088    this(new ModifyableTableDescriptor(name));
089  }
090
091  /**
092   * Construct a table descriptor by cloning the descriptor passed as a parameter.
093   * <p>
094   * Makes a deep copy of the supplied descriptor.
095   * Can make a modifiable descriptor from an ImmutableHTableDescriptor.
096   * @param desc The descriptor.
097   */
098  public HTableDescriptor(final HTableDescriptor desc) {
099    this(desc, true);
100  }
101
102  protected HTableDescriptor(final HTableDescriptor desc, boolean deepClone) {
103    this(deepClone ? new ModifyableTableDescriptor(desc.getTableName(), desc)
104      : desc.delegatee);
105  }
106
107  public HTableDescriptor(final TableDescriptor desc) {
108    this(new ModifyableTableDescriptor(desc.getTableName(), desc));
109  }
110
111  /**
112   * Construct a table descriptor by cloning the descriptor passed as a parameter
113   * but using a different table name.
114   * <p>
115   * Makes a deep copy of the supplied descriptor.
116   * Can make a modifiable descriptor from an ImmutableHTableDescriptor.
117   * @param name Table name.
118   * @param desc The descriptor.
119   */
120  public HTableDescriptor(final TableName name, final HTableDescriptor desc) {
121    this(new ModifyableTableDescriptor(name, desc));
122  }
123
124  protected HTableDescriptor(ModifyableTableDescriptor delegatee) {
125    this.delegatee = delegatee;
126  }
127
128  /**
129   * This is vestigial API. It will be removed in 3.0.
130   *
131   * @return always return the false
132   */
133  public boolean isRootRegion() {
134    return false;
135  }
136
137  /**
138   * Checks if this table is <code> hbase:meta </code>
139   * region.
140   *
141   * @return true if this table is <code> hbase:meta </code>
142   * region
143   */
144  @Override
145  public boolean isMetaRegion() {
146    return delegatee.isMetaRegion();
147  }
148
149  /**
150   * Checks if the table is a <code>hbase:meta</code> table
151   *
152   * @return true if table is <code> hbase:meta </code> region.
153   */
154  @Override
155  public boolean isMetaTable() {
156    return delegatee.isMetaTable();
157  }
158
159  /**
160   * @return Getter for fetching an unmodifiable map.
161   */
162  @Override
163  public Map<Bytes, Bytes> getValues() {
164    return delegatee.getValues();
165  }
166
167  /**
168   * Setter for storing metadata as a (key, value) pair in map
169   *
170   * @param key The key.
171   * @param value The value. If null, removes the setting.
172   */
173  public HTableDescriptor setValue(byte[] key, byte[] value) {
174    getDelegateeForModification().setValue(key, value);
175    return this;
176  }
177
178  /*
179   * Setter for storing metadata as a (key, value) pair in map
180   *
181   * @param key The key.
182   * @param value The value. If null, removes the setting.
183   */
184  public HTableDescriptor setValue(final Bytes key, final Bytes value) {
185    getDelegateeForModification().setValue(key, value);
186    return this;
187  }
188
189  /**
190   * Setter for storing metadata as a (key, value) pair in map
191   *
192   * @param key The key.
193   * @param value The value. If null, removes the setting.
194   */
195  public HTableDescriptor setValue(String key, String value) {
196    getDelegateeForModification().setValue(key, value);
197    return this;
198  }
199
200  /**
201   * Remove metadata represented by the key from the map
202   *
203   * @param key Key whose key and value we're to remove from HTableDescriptor
204   * parameters.
205   */
206  public void remove(final String key) {
207    getDelegateeForModification().removeValue(Bytes.toBytes(key));
208  }
209
210  /**
211   * Remove metadata represented by the key from the map
212   *
213   * @param key Key whose key and value we're to remove from HTableDescriptor
214   * parameters.
215   */
216  public void remove(Bytes key) {
217    getDelegateeForModification().removeValue(key);
218  }
219
220  /**
221   * Remove metadata represented by the key from the map
222   *
223   * @param key Key whose key and value we're to remove from HTableDescriptor
224   * parameters.
225   */
226  public void remove(final byte [] key) {
227    getDelegateeForModification().removeValue(key);
228  }
229
230  /**
231   * Check if the readOnly flag of the table is set. If the readOnly flag is
232   * set then the contents of the table can only be read from but not modified.
233   *
234   * @return true if all columns in the table should be read only
235   */
236  @Override
237  public boolean isReadOnly() {
238    return delegatee.isReadOnly();
239  }
240
241  /**
242   * Setting the table as read only sets all the columns in the table as read
243   * only. By default all tables are modifiable, but if the readOnly flag is
244   * set to true then the contents of the table can only be read but not modified.
245   *
246   * @param readOnly True if all of the columns in the table should be read
247   * only.
248   */
249  public HTableDescriptor setReadOnly(final boolean readOnly) {
250    getDelegateeForModification().setReadOnly(readOnly);
251    return this;
252  }
253
254  /**
255   * Check if the compaction enable flag of the table is true. If flag is
256   * false then no minor/major compactions will be done in real.
257   *
258   * @return true if table compaction enabled
259   */
260  @Override
261  public boolean isCompactionEnabled() {
262    return delegatee.isCompactionEnabled();
263  }
264
265  /**
266   * Setting the table compaction enable flag.
267   *
268   * @param isEnable True if enable compaction.
269   */
270  public HTableDescriptor setCompactionEnabled(final boolean isEnable) {
271    getDelegateeForModification().setCompactionEnabled(isEnable);
272    return this;
273  }
274
275  /**
276   * Check if the region split enable flag of the table is true. If flag is
277   * false then no split will be done.
278   *
279   * @return true if table region split enabled
280   */
281  @Override
282  public boolean isSplitEnabled() {
283    return delegatee.isSplitEnabled();
284  }
285
286  /**
287   * Setting the table region split enable flag.
288   *
289   * @param isEnable True if enable split.
290   */
291  public HTableDescriptor setSplitEnabled(final boolean isEnable) {
292    getDelegateeForModification().setSplitEnabled(isEnable);
293    return this;
294  }
295
296
297  /**
298   * Check if the region merge enable flag of the table is true. If flag is
299   * false then no merge will be done.
300   *
301   * @return true if table region merge enabled
302   */
303  @Override
304  public boolean isMergeEnabled() {
305    return delegatee.isMergeEnabled();
306  }
307
308  /**
309   * Setting the table region merge enable flag.
310   *
311   * @param isEnable True if enable merge.
312   */
313  public HTableDescriptor setMergeEnabled(final boolean isEnable) {
314    getDelegateeForModification().setMergeEnabled(isEnable);
315    return this;
316  }
317
318  /**
319   * Check if normalization enable flag of the table is true. If flag is
320   * false then no region normalizer won't attempt to normalize this table.
321   *
322   * @return true if region normalization is enabled for this table
323   */
324  @Override
325  public boolean isNormalizationEnabled() {
326    return delegatee.isNormalizationEnabled();
327  }
328
329  /**
330   * Setting the table normalization enable flag.
331   *
332   * @param isEnable True if enable normalization.
333   */
334  public HTableDescriptor setNormalizationEnabled(final boolean isEnable) {
335    getDelegateeForModification().setNormalizationEnabled(isEnable);
336    return this;
337  }
338
339  @Override
340  public int getNormalizerTargetRegionCount() {
341    return getDelegateeForModification().getNormalizerTargetRegionCount();
342  }
343
344  public HTableDescriptor setNormalizerTargetRegionCount(final int regionCount) {
345    getDelegateeForModification().setNormalizerTargetRegionCount(regionCount);
346    return this;
347  }
348
349  @Override
350  public long getNormalizerTargetRegionSize() {
351    return getDelegateeForModification().getNormalizerTargetRegionSize();
352  }
353
354  public HTableDescriptor setNormalizerTargetRegionSize(final long regionSize) {
355    getDelegateeForModification().setNormalizerTargetRegionSize(regionSize);
356    return this;
357  }
358
359  /**
360   * Sets the {@link Durability} setting for the table. This defaults to Durability.USE_DEFAULT.
361   * @param durability enum value
362   */
363  public HTableDescriptor setDurability(Durability durability) {
364    getDelegateeForModification().setDurability(durability);
365    return this;
366  }
367
368  /**
369   * Returns the durability setting for the table.
370   * @return durability setting for the table.
371   */
372  @Override
373  public Durability getDurability() {
374    return delegatee.getDurability();
375  }
376
377  /**
378   * Get the name of the table
379   *
380   * @return TableName
381   */
382  @Override
383  public TableName getTableName() {
384    return delegatee.getTableName();
385  }
386
387  /**
388   * Get the name of the table as a String
389   *
390   * @return name of table as a String
391   */
392  public String getNameAsString() {
393    return delegatee.getTableName().getNameAsString();
394  }
395
396  /**
397   * This sets the class associated with the region split policy which
398   * determines when a region split should occur.  The class used by
399   * default is defined in org.apache.hadoop.hbase.regionserver.RegionSplitPolicy
400   * @param clazz the class name
401   */
402  public HTableDescriptor setRegionSplitPolicyClassName(String clazz) {
403    getDelegateeForModification().setRegionSplitPolicyClassName(clazz);
404    return this;
405  }
406
407  /**
408   * This gets the class associated with the region split policy which
409   * determines when a region split should occur.  The class used by
410   * default is defined in org.apache.hadoop.hbase.regionserver.RegionSplitPolicy
411   *
412   * @return the class name of the region split policy for this table.
413   * If this returns null, the default split policy is used.
414   */
415  @Override
416   public String getRegionSplitPolicyClassName() {
417    return delegatee.getRegionSplitPolicyClassName();
418  }
419
420  /**
421   * Returns the maximum size upto which a region can grow to after which a region
422   * split is triggered. The region size is represented by the size of the biggest
423   * store file in that region.
424   *
425   * @return max hregion size for table, -1 if not set.
426   *
427   * @see #setMaxFileSize(long)
428   */
429   @Override
430  public long getMaxFileSize() {
431    return delegatee.getMaxFileSize();
432  }
433
434  /**
435   * Sets the maximum size upto which a region can grow to after which a region
436   * split is triggered. The region size is represented by the size of the biggest
437   * store file in that region, i.e. If the biggest store file grows beyond the
438   * maxFileSize, then the region split is triggered. This defaults to a value of
439   * 256 MB.
440   * <p>
441   * This is not an absolute value and might vary. Assume that a single row exceeds
442   * the maxFileSize then the storeFileSize will be greater than maxFileSize since
443   * a single row cannot be split across multiple regions
444   * </p>
445   *
446   * @param maxFileSize The maximum file size that a store file can grow to
447   * before a split is triggered.
448   */
449  public HTableDescriptor setMaxFileSize(long maxFileSize) {
450    getDelegateeForModification().setMaxFileSize(maxFileSize);
451    return this;
452  }
453
454  /**
455   * Returns the size of the memstore after which a flush to filesystem is triggered.
456   *
457   * @return memory cache flush size for each hregion, -1 if not set.
458   *
459   * @see #setMemStoreFlushSize(long)
460   */
461  @Override
462  public long getMemStoreFlushSize() {
463    return delegatee.getMemStoreFlushSize();
464  }
465
466  /**
467   * Represents the maximum size of the memstore after which the contents of the
468   * memstore are flushed to the filesystem. This defaults to a size of 64 MB.
469   *
470   * @param memstoreFlushSize memory cache flush size for each hregion
471   */
472  public HTableDescriptor setMemStoreFlushSize(long memstoreFlushSize) {
473    getDelegateeForModification().setMemStoreFlushSize(memstoreFlushSize);
474    return this;
475  }
476
477  /**
478   * This sets the class associated with the flush policy which determines determines the stores
479   * need to be flushed when flushing a region. The class used by default is defined in
480   * org.apache.hadoop.hbase.regionserver.FlushPolicy.
481   * @param clazz the class name
482   */
483  public HTableDescriptor setFlushPolicyClassName(String clazz) {
484    getDelegateeForModification().setFlushPolicyClassName(clazz);
485    return this;
486  }
487
488  /**
489   * This gets the class associated with the flush policy which determines the stores need to be
490   * flushed when flushing a region. The class used by default is defined in
491   * org.apache.hadoop.hbase.regionserver.FlushPolicy.
492   * @return the class name of the flush policy for this table. If this returns null, the default
493   *         flush policy is used.
494   */
495  @Override
496  public String getFlushPolicyClassName() {
497    return delegatee.getFlushPolicyClassName();
498  }
499
500  /**
501   * Adds a column family.
502   * For the updating purpose please use {@link #modifyFamily(HColumnDescriptor)} instead.
503   * @param family HColumnDescriptor of family to add.
504   */
505  public HTableDescriptor addFamily(final HColumnDescriptor family) {
506    getDelegateeForModification().setColumnFamily(family);
507    return this;
508  }
509
510  /**
511   * Modifies the existing column family.
512   * @param family HColumnDescriptor of family to update
513   * @return this (for chained invocation)
514   */
515  public HTableDescriptor modifyFamily(final HColumnDescriptor family) {
516    getDelegateeForModification().modifyColumnFamily(family);
517    return this;
518  }
519
520  /**
521   * Checks to see if this table contains the given column family
522   * @param familyName Family name or column name.
523   * @return true if the table contains the specified family name
524   */
525  public boolean hasFamily(final byte [] familyName) {
526    return delegatee.hasColumnFamily(familyName);
527  }
528
529  /**
530   * @return Name of this table and then a map of all of the column family
531   * descriptors.
532   * @see #getNameAsString()
533   */
534  @Override
535  public String toString() {
536    return delegatee.toString();
537  }
538
539  /**
540   * @return Name of this table and then a map of all of the column family
541   * descriptors (with only the non-default column family attributes)
542   */
543  @Override
544  public String toStringCustomizedValues() {
545    return delegatee.toStringCustomizedValues();
546  }
547
548  /**
549   * @return map of all table attributes formatted into string.
550   */
551  public String toStringTableAttributes() {
552   return delegatee.toStringTableAttributes();
553  }
554
555  /**
556   * Compare the contents of the descriptor with another one passed as a parameter.
557   * Checks if the obj passed is an instance of HTableDescriptor, if yes then the
558   * contents of the descriptors are compared.
559   *
560   * @return true if the contents of the the two descriptors exactly match
561   *
562   * @see java.lang.Object#equals(java.lang.Object)
563   */
564  @Override
565  public boolean equals(Object obj) {
566    if (this == obj) {
567      return true;
568    }
569    if (obj instanceof HTableDescriptor) {
570      return delegatee.equals(((HTableDescriptor) obj).delegatee);
571    }
572    return false;
573  }
574
575  /**
576   * @see java.lang.Object#hashCode()
577   */
578  @Override
579  public int hashCode() {
580    return delegatee.hashCode();
581  }
582
583  // Comparable
584
585  /**
586   * Compares the descriptor with another descriptor which is passed as a parameter.
587   * This compares the content of the two descriptors and not the reference.
588   *
589   * @return 0 if the contents of the descriptors are exactly matching,
590   *         1 if there is a mismatch in the contents
591   */
592  @Override
593  public int compareTo(final HTableDescriptor other) {
594    return TableDescriptor.COMPARATOR.compare(this, other);
595  }
596
597  /**
598   * Returns an unmodifiable collection of all the {@link HColumnDescriptor}
599   * of all the column families of the table.
600   * @deprecated Use {@link #getColumnFamilies}.
601   * @return Immutable collection of {@link HColumnDescriptor} of all the
602   * column families.
603   */
604  @Deprecated
605  public Collection<HColumnDescriptor> getFamilies() {
606    return Stream.of(delegatee.getColumnFamilies())
607            .map(this::toHColumnDescriptor)
608            .collect(Collectors.toList());
609  }
610
611  /**
612   * Returns the configured replicas per region
613   */
614  @Override
615  public int getRegionReplication() {
616    return delegatee.getRegionReplication();
617  }
618
619  /**
620   * Sets the number of replicas per region.
621   * @param regionReplication the replication factor per region
622   */
623  public HTableDescriptor setRegionReplication(int regionReplication) {
624    getDelegateeForModification().setRegionReplication(regionReplication);
625    return this;
626  }
627
628  /**
629   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0.
630   *             Use {@link #hasRegionMemStoreReplication()} instead
631   */
632  @Deprecated
633  public boolean hasRegionMemstoreReplication() {
634    return hasRegionMemStoreReplication();
635  }
636
637  /**
638   * @return true if the read-replicas memstore replication is enabled.
639   */
640  @Override
641  public boolean hasRegionMemStoreReplication() {
642    return delegatee.hasRegionMemStoreReplication();
643  }
644
645  /**
646   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0.
647   *             Use {@link #setRegionMemStoreReplication(boolean)} instead
648   */
649  @Deprecated
650  public HTableDescriptor setRegionMemstoreReplication(boolean memstoreReplication) {
651    return setRegionMemStoreReplication(memstoreReplication);
652  }
653
654  /**
655   * Enable or Disable the memstore replication from the primary region to the replicas.
656   * The replication will be used only for meta operations (e.g. flush, compaction, ...)
657   *
658   * @param memstoreReplication true if the new data written to the primary region
659   *                                 should be replicated.
660   *                            false if the secondaries can tollerate to have new
661   *                                  data only when the primary flushes the memstore.
662   */
663  public HTableDescriptor setRegionMemStoreReplication(boolean memstoreReplication) {
664    getDelegateeForModification().setRegionMemStoreReplication(memstoreReplication);
665    return this;
666  }
667
668  public HTableDescriptor setPriority(int priority) {
669    getDelegateeForModification().setPriority(priority);
670    return this;
671  }
672
673  @Override
674  public int getPriority() {
675    return delegatee.getPriority();
676  }
677
678  /**
679   * Returns all the column family names of the current table. The map of
680   * HTableDescriptor contains mapping of family name to HColumnDescriptors.
681   * This returns all the keys of the family map which represents the column
682   * family names of the table.
683   *
684   * @return Immutable sorted set of the keys of the families.
685   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0
686   *             (<a href="https://issues.apache.org/jira/browse/HBASE-18008">HBASE-18008</a>).
687   *             Use {@link #getColumnFamilyNames()}.
688   */
689  @Deprecated
690  public Set<byte[]> getFamiliesKeys() {
691    return delegatee.getColumnFamilyNames();
692  }
693
694  /**
695   * Returns the count of the column families of the table.
696   *
697   * @return Count of column families of the table
698   */
699  @Override
700  public int getColumnFamilyCount() {
701    return delegatee.getColumnFamilyCount();
702  }
703
704  /**
705   * Returns an array all the {@link HColumnDescriptor} of the column families
706   * of the table.
707   *
708   * @return Array of all the HColumnDescriptors of the current table
709   *
710   * @see #getFamilies()
711   */
712  @Deprecated
713  @Override
714  public HColumnDescriptor[] getColumnFamilies() {
715    return Stream.of(delegatee.getColumnFamilies())
716            .map(this::toHColumnDescriptor)
717            .toArray(size -> new HColumnDescriptor[size]);
718  }
719
720  /**
721   * Returns the HColumnDescriptor for a specific column family with name as
722   * specified by the parameter column.
723   * @param column Column family name
724   * @return Column descriptor for the passed family name or the family on
725   * passed in column.
726   * @deprecated Use {@link #getColumnFamily(byte[])}.
727   */
728  @Deprecated
729  public HColumnDescriptor getFamily(final byte[] column) {
730    return toHColumnDescriptor(delegatee.getColumnFamily(column));
731  }
732
733
734  /**
735   * Removes the HColumnDescriptor with name specified by the parameter column
736   * from the table descriptor
737   *
738   * @param column Name of the column family to be removed.
739   * @return Column descriptor for the passed family name or the family on
740   * passed in column.
741   */
742  public HColumnDescriptor removeFamily(final byte [] column) {
743    return toHColumnDescriptor(getDelegateeForModification().removeColumnFamily(column));
744  }
745
746  /**
747   * Return a HColumnDescriptor for user to keep the compatibility as much as possible.
748   * @param desc read-only ColumnFamilyDescriptor
749   * @return The older implementation of ColumnFamilyDescriptor
750   */
751  protected HColumnDescriptor toHColumnDescriptor(ColumnFamilyDescriptor desc) {
752    if (desc == null) {
753      return null;
754    } else if (desc instanceof ModifyableColumnFamilyDescriptor) {
755      return new HColumnDescriptor((ModifyableColumnFamilyDescriptor) desc);
756    } else if (desc instanceof HColumnDescriptor) {
757      return (HColumnDescriptor) desc;
758    } else {
759      return new HColumnDescriptor(new ModifyableColumnFamilyDescriptor(desc));
760    }
761  }
762
763  /**
764   * Add a table coprocessor to this table. The coprocessor
765   * type must be org.apache.hadoop.hbase.coprocessor.RegionCoprocessor.
766   * It won't check if the class can be loaded or not.
767   * Whether a coprocessor is loadable or not will be determined when
768   * a region is opened.
769   * @param className Full class name.
770   * @throws IOException
771   */
772  public HTableDescriptor addCoprocessor(String className) throws IOException {
773    getDelegateeForModification().setCoprocessor(className);
774    return this;
775  }
776
777  /**
778   * Add a table coprocessor to this table. The coprocessor
779   * type must be org.apache.hadoop.hbase.coprocessor.RegionCoprocessor.
780   * It won't check if the class can be loaded or not.
781   * Whether a coprocessor is loadable or not will be determined when
782   * a region is opened.
783   * @param jarFilePath Path of the jar file. If it's null, the class will be
784   * loaded from default classloader.
785   * @param className Full class name.
786   * @param priority Priority
787   * @param kvs Arbitrary key-value parameter pairs passed into the coprocessor.
788   * @throws IOException
789   */
790  public HTableDescriptor addCoprocessor(String className, Path jarFilePath,
791                             int priority, final Map<String, String> kvs)
792  throws IOException {
793    getDelegateeForModification().setCoprocessor(
794      CoprocessorDescriptorBuilder.newBuilder(className)
795        .setJarPath(jarFilePath == null ? null : jarFilePath.toString())
796        .setPriority(priority)
797        .setProperties(kvs == null ? Collections.emptyMap() : kvs)
798        .build());
799    return this;
800  }
801
802  /**
803   * Add a table coprocessor to this table. The coprocessor
804   * type must be org.apache.hadoop.hbase.coprocessor.RegionCoprocessor.
805   * It won't check if the class can be loaded or not.
806   * Whether a coprocessor is loadable or not will be determined when
807   * a region is opened.
808   * @param specStr The Coprocessor specification all in in one String formatted so matches
809   * {@link HConstants#CP_HTD_ATTR_VALUE_PATTERN}
810   * @throws IOException
811   */
812  public HTableDescriptor addCoprocessorWithSpec(final String specStr) throws IOException {
813    getDelegateeForModification().setCoprocessorWithSpec(specStr);
814    return this;
815  }
816
817  /**
818   * Check if the table has an attached co-processor represented by the name className
819   *
820   * @param classNameToMatch - Class name of the co-processor
821   * @return true of the table has a co-processor className
822   */
823  @Override
824  public boolean hasCoprocessor(String classNameToMatch) {
825    return delegatee.hasCoprocessor(classNameToMatch);
826  }
827
828  @Override
829  public Collection<CoprocessorDescriptor> getCoprocessorDescriptors() {
830    return delegatee.getCoprocessorDescriptors();
831  }
832
833  /**
834   * Remove a coprocessor from those set on the table
835   * @param className Class name of the co-processor
836   */
837  public void removeCoprocessor(String className) {
838    getDelegateeForModification().removeCoprocessor(className);
839  }
840
841  public final static String NAMESPACE_FAMILY_INFO = TableDescriptorBuilder.NAMESPACE_FAMILY_INFO;
842  public final static byte[] NAMESPACE_FAMILY_INFO_BYTES = TableDescriptorBuilder.NAMESPACE_FAMILY_INFO_BYTES;
843  public final static byte[] NAMESPACE_COL_DESC_BYTES = TableDescriptorBuilder.NAMESPACE_COL_DESC_BYTES;
844
845  /** Table descriptor for namespace table */
846  public static final HTableDescriptor NAMESPACE_TABLEDESC
847    = new HTableDescriptor(TableDescriptorBuilder.NAMESPACE_TABLEDESC);
848
849  @Deprecated
850  public HTableDescriptor setOwner(User owner) {
851    getDelegateeForModification().setOwner(owner);
852    return this;
853  }
854
855  // used by admin.rb:alter(table_name,*args) to update owner.
856  @Deprecated
857  public HTableDescriptor setOwnerString(String ownerString) {
858    getDelegateeForModification().setOwnerString(ownerString);
859    return this;
860  }
861
862  @Override
863  @Deprecated
864  public String getOwnerString() {
865    return delegatee.getOwnerString();
866  }
867
868  /**
869   * @return This instance serialized with pb with pb magic prefix
870   * @see #parseFrom(byte[])
871   */
872  public byte[] toByteArray() {
873    return TableDescriptorBuilder.toByteArray(delegatee);
874  }
875
876  /**
877   * @param bytes A pb serialized {@link HTableDescriptor} instance with pb magic prefix
878   * @return An instance of {@link HTableDescriptor} made from <code>bytes</code>
879   * @throws DeserializationException
880   * @throws IOException
881   * @see #toByteArray()
882   */
883  public static HTableDescriptor parseFrom(final byte [] bytes)
884  throws DeserializationException, IOException {
885    TableDescriptor desc = TableDescriptorBuilder.parseFrom(bytes);
886    if (desc instanceof ModifyableTableDescriptor) {
887      return new HTableDescriptor((ModifyableTableDescriptor) desc);
888    } else {
889      return new HTableDescriptor(desc);
890    }
891  }
892
893  /**
894   * Getter for accessing the configuration value by key
895   */
896  public String getConfigurationValue(String key) {
897    return delegatee.getValue(key);
898  }
899
900  /**
901   * Getter for fetching an unmodifiable map.
902   */
903  public Map<String, String> getConfiguration() {
904    return delegatee.getValues().entrySet().stream()
905            .collect(Collectors.toMap(
906                    e -> Bytes.toString(e.getKey().get(), e.getKey().getOffset(), e.getKey().getLength()),
907                    e -> Bytes.toString(e.getValue().get(), e.getValue().getOffset(), e.getValue().getLength())
908            ));
909  }
910
911  /**
912   * Setter for storing a configuration setting in map.
913   * @param key Config key. Same as XML config key e.g. hbase.something.or.other.
914   * @param value String value. If null, removes the setting.
915   */
916  public HTableDescriptor setConfiguration(String key, String value) {
917    getDelegateeForModification().setValue(key, value);
918    return this;
919  }
920
921  /**
922   * Remove a config setting represented by the key from the map
923   */
924  public void removeConfiguration(final String key) {
925    getDelegateeForModification().removeValue(Bytes.toBytes(key));
926  }
927
928  @Override
929  public Bytes getValue(Bytes key) {
930    return delegatee.getValue(key);
931  }
932
933  @Override
934  public String getValue(String key) {
935    return delegatee.getValue(key);
936  }
937
938  @Override
939  public byte[] getValue(byte[] key) {
940    return delegatee.getValue(key);
941  }
942
943  @Override
944  public Set<byte[]> getColumnFamilyNames() {
945    return delegatee.getColumnFamilyNames();
946  }
947
948  @Override
949  public boolean hasColumnFamily(byte[] name) {
950    return delegatee.hasColumnFamily(name);
951  }
952
953  @Override
954  public ColumnFamilyDescriptor getColumnFamily(byte[] name) {
955    return delegatee.getColumnFamily(name);
956  }
957
958  protected ModifyableTableDescriptor getDelegateeForModification() {
959    return delegatee;
960  }
961}