001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.regionserver; 019 020import java.util.Arrays; 021 022import org.apache.yetus.audience.InterfaceAudience; 023import org.slf4j.Logger; 024import org.slf4j.LoggerFactory; 025 026/** 027 * A custom RegionSplitPolicy implementing a SplitPolicy that groups 028 * rows by a prefix of the row-key 029 * 030 * This ensures that a region is not split "inside" a prefix of a row key. 031 * I.e. rows can be co-located in a region by their prefix. 032 */ 033@InterfaceAudience.Private 034public class KeyPrefixRegionSplitPolicy extends IncreasingToUpperBoundRegionSplitPolicy { 035 private static final Logger LOG = LoggerFactory 036 .getLogger(KeyPrefixRegionSplitPolicy.class); 037 @Deprecated 038 public static final String PREFIX_LENGTH_KEY_DEPRECATED = "prefix_split_key_policy.prefix_length"; 039 public static final String PREFIX_LENGTH_KEY = "KeyPrefixRegionSplitPolicy.prefix_length"; 040 041 private int prefixLength = 0; 042 043 @Override 044 protected void configureForRegion(HRegion region) { 045 super.configureForRegion(region); 046 prefixLength = 0; 047 048 // read the prefix length from the table descriptor 049 String prefixLengthString = region.getTableDescriptor().getValue( 050 PREFIX_LENGTH_KEY); 051 if (prefixLengthString == null) { 052 //read the deprecated value 053 prefixLengthString = region.getTableDescriptor().getValue(PREFIX_LENGTH_KEY_DEPRECATED); 054 if (prefixLengthString == null) { 055 LOG.error(PREFIX_LENGTH_KEY + " not specified for table " 056 + region.getTableDescriptor().getTableName() 057 + ". Using default RegionSplitPolicy"); 058 return; 059 } 060 } 061 try { 062 prefixLength = Integer.parseInt(prefixLengthString); 063 } catch (NumberFormatException nfe) { 064 /* Differentiate NumberFormatException from an invalid value range reported below. */ 065 LOG.error("Number format exception when parsing " + PREFIX_LENGTH_KEY + " for table " 066 + region.getTableDescriptor().getTableName() + ":" 067 + prefixLengthString + ". " + nfe); 068 return; 069 } 070 if (prefixLength <= 0) { 071 LOG.error("Invalid value for " + PREFIX_LENGTH_KEY + " for table " 072 + region.getTableDescriptor().getTableName() + ":" 073 + prefixLengthString + ". Using default RegionSplitPolicy"); 074 } 075 } 076 077 @Override 078 protected byte[] getSplitPoint() { 079 byte[] splitPoint = super.getSplitPoint(); 080 if (prefixLength > 0 && splitPoint != null && splitPoint.length > 0) { 081 // group split keys by a prefix 082 return Arrays.copyOf(splitPoint, 083 Math.min(prefixLength, splitPoint.length)); 084 } else { 085 return splitPoint; 086 } 087 } 088}