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;
021import org.apache.hadoop.hbase.util.Bytes;
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 rows by a prefix of the row-key
028 * with a delimiter. Only the first delimiter for the row key will define the prefix of the row key
029 * that is used for grouping. This ensures that a region is not split "inside" a prefix of a row
030 * key. I.e. rows can be co-located in a region by their prefix. As an example, if you have row keys
031 * delimited with <code>_</code>, like <code>userid_eventtype_eventid</code>, and use prefix
032 * delimiter _, this split policy ensures that all rows starting with the same userid, belongs to
033 * the same region.
034 * @see KeyPrefixRegionSplitPolicy
035 * @deprecated since 3.0.0 and will be removed in 4.0.0. Use {@link RegionSplitRestriction},
036 *             instead.
037 */
038@Deprecated
039@InterfaceAudience.Private
040public class DelimitedKeyPrefixRegionSplitPolicy extends IncreasingToUpperBoundRegionSplitPolicy {
041
042  private static final Logger LOG =
043    LoggerFactory.getLogger(DelimitedKeyPrefixRegionSplitPolicy.class);
044  public static final String DELIMITER_KEY = "DelimitedKeyPrefixRegionSplitPolicy.delimiter";
045
046  private byte[] delimiter = null;
047
048  @Override
049  public String toString() {
050    return "DelimitedKeyPrefixRegionSplitPolicy{" + "delimiter=" + Bytes.toStringBinary(delimiter)
051      + ", " + super.toString() + '}';
052  }
053
054  @Override
055  protected void configureForRegion(HRegion region) {
056    super.configureForRegion(region);
057    // read the prefix length from the table descriptor
058    String delimiterString = region.getTableDescriptor().getValue(DELIMITER_KEY);
059    if (delimiterString == null || delimiterString.length() == 0) {
060      LOG.error(DELIMITER_KEY + " not specified for table "
061        + region.getTableDescriptor().getTableName() + ". Using default RegionSplitPolicy");
062      return;
063    }
064    delimiter = Bytes.toBytes(delimiterString);
065  }
066
067  @Override
068  protected byte[] getSplitPoint() {
069    byte[] splitPoint = super.getSplitPoint();
070    if (splitPoint != null && delimiter != null) {
071
072      // find the first occurrence of delimiter in split point
073      int index = org.apache.hbase.thirdparty.com.google.common.primitives.Bytes.indexOf(splitPoint,
074        delimiter);
075      if (index < 0) {
076        LOG.warn("Delimiter " + Bytes.toString(delimiter) + "  not found for split key "
077          + Bytes.toString(splitPoint));
078        return splitPoint;
079      }
080
081      // group split keys by a prefix
082      return Arrays.copyOf(splitPoint, Math.min(index, splitPoint.length));
083    } else {
084      return splitPoint;
085    }
086  }
087}