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.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      if (region != null) {
47        prefixLength = 0;
48  
49        // read the prefix length from the table descriptor
50        String prefixLengthString = region.getTableDesc().getValue(
51            PREFIX_LENGTH_KEY);
52        if (prefixLengthString == null) {
53          //read the deprecated value
54          prefixLengthString = region.getTableDesc().getValue(PREFIX_LENGTH_KEY_DEPRECATED);
55          if (prefixLengthString == null) {
56            LOG.error(PREFIX_LENGTH_KEY + " not specified for table "
57                + region.getTableDesc().getTableName()
58                + ". Using default RegionSplitPolicy");
59            return;
60          }
61        }
62        try {
63          prefixLength = Integer.parseInt(prefixLengthString);
64        } catch (NumberFormatException nfe) {
65          /* Differentiate NumberFormatException from an invalid value range reported below. */
66          LOG.error("Number format exception when parsing " + PREFIX_LENGTH_KEY + " for table "
67              + region.getTableDesc().getTableName() + ":"
68              + prefixLengthString + ". " + nfe);
69          return;
70        }
71        if (prefixLength <= 0) {
72          LOG.error("Invalid value for " + PREFIX_LENGTH_KEY + " for table "
73              + region.getTableDesc().getTableName() + ":"
74              + prefixLengthString + ". Using default RegionSplitPolicy");
75        }
76      }
77    }
78  
79    @Override
80    protected byte[] getSplitPoint() {
81      byte[] splitPoint = super.getSplitPoint();
82      if (prefixLength > 0 && splitPoint != null && splitPoint.length > 0) {
83        // group split keys by a prefix
84        return Arrays.copyOf(splitPoint,
85            Math.min(prefixLength, splitPoint.length));
86      } else {
87        return splitPoint;
88      }
89    }
90  }