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.conf.Configuration;
24  import org.apache.hadoop.conf.Configured;
25  import org.apache.hadoop.hbase.HConstants;
26  import org.apache.hadoop.hbase.HTableDescriptor;
27  import org.apache.hadoop.util.ReflectionUtils;
28  
29  import com.google.common.base.Preconditions;
30  
31  /**
32   * A split policy determines when a region should be split.
33   * {@see ConstantSizeRegionSplitPolicy}
34   */
35  abstract class RegionSplitPolicy extends Configured {
36    private static final Class<ConstantSizeRegionSplitPolicy>
37      DEFAULT_SPLIT_POLICY_CLASS = ConstantSizeRegionSplitPolicy.class;
38  
39    /**
40     * The region configured for this split policy.
41     */
42    protected HRegion region;
43    
44    /**
45     * Upon construction, this method will be called with the region
46     * to be governed. It will be called once and only once.
47     */
48    void configureForRegion(HRegion region) {
49      Preconditions.checkState(
50          this.region == null,
51          "Policy already configured for region {}",
52          this.region);
53      
54      this.region = region;
55    }
56  
57    /**
58     * @return true if the specified region should be split.
59     */
60    abstract boolean shouldSplit();
61  
62    /**
63     * @return the key at which the region should be split, or null
64     * if it cannot be split. This will only be called if shouldSplit
65     * previously returned true.
66     */
67    byte[] getSplitPoint() {
68      Map<byte[], Store> stores = region.getStores();
69  
70      byte[] splitPointFromLargestStore = null;
71      long largestStoreSize = 0;
72      for (Store s : stores.values()) {
73        byte[] splitPoint = s.getSplitPoint();
74        long storeSize = s.getSize();
75        if (splitPoint != null && largestStoreSize < storeSize) {
76          splitPointFromLargestStore = splitPoint;
77          largestStoreSize = storeSize;
78        }
79      }
80      
81      return splitPointFromLargestStore;
82    }
83  
84    /**
85     * Create the RegionSplitPolicy configured for the given table.
86     * Each
87     * @param htd
88     * @param conf
89     * @return
90     * @throws IOException
91     */
92    public static RegionSplitPolicy create(HRegion region,
93        Configuration conf) throws IOException {
94      
95      Class<? extends RegionSplitPolicy> clazz = getSplitPolicyClass(
96          region.getTableDesc(), conf);
97      RegionSplitPolicy policy = ReflectionUtils.newInstance(clazz, conf);
98      policy.configureForRegion(region);
99      return policy;
100   }
101   
102   static Class<? extends RegionSplitPolicy> getSplitPolicyClass(
103       HTableDescriptor htd, Configuration conf) throws IOException {
104     String className = htd.getRegionSplitPolicyClassName();
105     if (className == null) {
106       className = conf.get(HConstants.HBASE_REGION_SPLIT_POLICY_KEY,
107           DEFAULT_SPLIT_POLICY_CLASS.getName());
108     }
109 
110     try {
111       Class<? extends RegionSplitPolicy> clazz =
112         Class.forName(className).asSubclass(RegionSplitPolicy.class);
113       return clazz;
114     } catch (Exception  e) {
115       throw new IOException(
116           "Unable to load configured region split policy '" +
117           className + "' for table '" + htd.getNameAsString() + "'",
118           e);
119     }
120   }
121 
122 }