View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase.regionserver;
19  
20  import java.io.IOException;
21  import java.util.Map;
22  
23  import org.apache.hadoop.classification.InterfaceAudience;
24  import org.apache.hadoop.conf.Configuration;
25  import org.apache.hadoop.conf.Configured;
26  import org.apache.hadoop.hbase.HConstants;
27  import org.apache.hadoop.hbase.HTableDescriptor;
28  import org.apache.hadoop.util.ReflectionUtils;
29  
30  import com.google.common.base.Preconditions;
31  
32  /**
33   * A split policy determines when a region should be split.
34   * @see IncreasingToUpperBoundRegionSplitPolicy Default split policy since
35   *      0.94.0
36   * @see ConstantSizeRegionSplitPolicy Default split policy before 0.94.0
37   */
38  @InterfaceAudience.Private
39  public abstract class RegionSplitPolicy extends Configured {
40    private static final Class<? extends RegionSplitPolicy>
41      DEFAULT_SPLIT_POLICY_CLASS = IncreasingToUpperBoundRegionSplitPolicy.class;
42  
43    /**
44     * The region configured for this split policy.
45     */
46    protected HRegion region;
47  
48    /**
49     * Upon construction, this method will be called with the region
50     * to be governed. It will be called once and only once.
51     */
52    protected void configureForRegion(HRegion region) {
53      Preconditions.checkState(
54          this.region == null,
55          "Policy already configured for region {}",
56          this.region);
57  
58      this.region = region;
59    }
60  
61    /**
62     * @return true if the specified region should be split.
63     */
64    protected abstract boolean shouldSplit();
65  
66    /**
67     * @return the key at which the region should be split, or null
68     * if it cannot be split. This will only be called if shouldSplit
69     * previously returned true.
70     */
71    protected byte[] getSplitPoint() {
72      byte[] explicitSplitPoint = this.region.getExplicitSplitPoint();
73      if (explicitSplitPoint != null) {
74        return explicitSplitPoint;
75      }
76      Map<byte[], Store> stores = region.getStores();
77  
78      byte[] splitPointFromLargestStore = null;
79      long largestStoreSize = 0;
80      for (Store s : stores.values()) {
81        byte[] splitPoint = s.getSplitPoint();
82        long storeSize = s.getSize();
83        if (splitPoint != null && largestStoreSize < storeSize) {
84          splitPointFromLargestStore = splitPoint;
85          largestStoreSize = storeSize;
86        }
87      }
88  
89      return splitPointFromLargestStore;
90    }
91  
92    /**
93     * Create the RegionSplitPolicy configured for the given table.
94     * @param region
95     * @param conf
96     * @return a RegionSplitPolicy
97     * @throws IOException
98     */
99    public static RegionSplitPolicy create(HRegion region,
100       Configuration conf) throws IOException {
101     Class<? extends RegionSplitPolicy> clazz = getSplitPolicyClass(
102         region.getTableDesc(), conf);
103     RegionSplitPolicy policy = ReflectionUtils.newInstance(clazz, conf);
104     policy.configureForRegion(region);
105     return policy;
106   }
107 
108   public static Class<? extends RegionSplitPolicy> getSplitPolicyClass(
109       HTableDescriptor htd, Configuration conf) throws IOException {
110     String className = htd.getRegionSplitPolicyClassName();
111     if (className == null) {
112       className = conf.get(HConstants.HBASE_REGION_SPLIT_POLICY_KEY,
113           DEFAULT_SPLIT_POLICY_CLASS.getName());
114     }
115 
116     try {
117       Class<? extends RegionSplitPolicy> clazz =
118         Class.forName(className).asSubclass(RegionSplitPolicy.class);
119       return clazz;
120     } catch (Exception  e) {
121       throw new IOException(
122           "Unable to load configured region split policy '" +
123           className + "' for table '" + htd.getTableName() + "'",
124           e);
125     }
126   }
127 }