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.util.Arrays;
21  
22  import org.apache.commons.logging.Log;
23  import org.apache.commons.logging.LogFactory;
24  import org.apache.hadoop.hbase.classification.InterfaceAudience;
25  
26  /**
27   * A custom RegionSplitPolicy implementing a SplitPolicy that groups
28   * rows by a prefix of the row-key
29   *
30   * This ensures that a region is not split "inside" a prefix of a row key.
31   * I.e. rows can be co-located in a region by their prefix.
32   */
33  @InterfaceAudience.Private
34  public class KeyPrefixRegionSplitPolicy extends IncreasingToUpperBoundRegionSplitPolicy {
35    private static final Log LOG = LogFactory
36        .getLog(KeyPrefixRegionSplitPolicy.class);
37    @Deprecated
38    public static final String PREFIX_LENGTH_KEY_DEPRECATED = "prefix_split_key_policy.prefix_length";
39    public static final String PREFIX_LENGTH_KEY = "KeyPrefixRegionSplitPolicy.prefix_length";
40  
41    private int prefixLength = 0;
42  
43    @Override
44    protected void configureForRegion(HRegion region) {
45      super.configureForRegion(region);
46      prefixLength = 0;
47  
48      // read the prefix length from the table descriptor
49      String prefixLengthString = region.getTableDesc().getValue(
50          PREFIX_LENGTH_KEY);
51      if (prefixLengthString == null) {
52        //read the deprecated value
53        prefixLengthString = region.getTableDesc().getValue(PREFIX_LENGTH_KEY_DEPRECATED);
54        if (prefixLengthString == null) {
55          LOG.error(PREFIX_LENGTH_KEY + " not specified for table "
56              + region.getTableDesc().getTableName()
57              + ". Using default RegionSplitPolicy");
58          return;
59        }
60      }
61      try {
62        prefixLength = Integer.parseInt(prefixLengthString);
63      } catch (NumberFormatException nfe) {
64        /* Differentiate NumberFormatException from an invalid value range reported below. */
65        LOG.error("Number format exception when parsing " + PREFIX_LENGTH_KEY + " for table "
66            + region.getTableDesc().getTableName() + ":"
67            + prefixLengthString + ". " + nfe);
68        return;
69      }
70      if (prefixLength <= 0) {
71        LOG.error("Invalid value for " + PREFIX_LENGTH_KEY + " for table "
72            + region.getTableDesc().getTableName() + ":"
73            + prefixLengthString + ". Using default RegionSplitPolicy");
74      }
75    }
76  
77    @Override
78    protected byte[] getSplitPoint() {
79      byte[] splitPoint = super.getSplitPoint();
80      if (prefixLength > 0 && splitPoint != null && splitPoint.length > 0) {
81        // group split keys by a prefix
82        return Arrays.copyOf(splitPoint,
83            Math.min(prefixLength, splitPoint.length));
84      } else {
85        return splitPoint;
86      }
87    }
88  }