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.io.IOException; 021import java.util.List; 022import org.apache.hadoop.conf.Configuration; 023import org.apache.hadoop.hbase.HConstants; 024import org.apache.hadoop.hbase.TableName; 025import org.apache.hadoop.hbase.client.TableDescriptor; 026import org.apache.hadoop.hbase.client.TableDescriptorBuilder; 027import org.apache.yetus.audience.InterfaceAudience; 028import org.slf4j.Logger; 029import org.slf4j.LoggerFactory; 030 031/** 032 * Split size is the number of regions that are on this server that all are of the same table, 033 * cubed, times 2x the region flush size OR the maximum region split size, whichever is smaller. 034 * <p> 035 * For example, if the flush size is 128MB, then after two flushes (256MB) we will split which will 036 * make two regions that will split when their size is {@code 2^3 * 128MB*2 = 2048MB}. 037 * <p> 038 * If one of these regions splits, then there are three regions and now the split size is 039 * {@code 3^3 * 128MB*2 = 6912MB}, and so on until we reach the configured maximum file size and 040 * then from there on out, we'll use that. 041 */ 042@InterfaceAudience.Private 043public class IncreasingToUpperBoundRegionSplitPolicy extends ConstantSizeRegionSplitPolicy { 044 private static final Logger LOG = 045 LoggerFactory.getLogger(IncreasingToUpperBoundRegionSplitPolicy.class); 046 047 protected long initialSize; 048 049 @Override 050 public String toString() { 051 return "IncreasingToUpperBoundRegionSplitPolicy{" + "initialSize=" + initialSize + ", " 052 + super.toString() + '}'; 053 } 054 055 @Override 056 protected void configureForRegion(HRegion region) { 057 super.configureForRegion(region); 058 Configuration conf = getConf(); 059 initialSize = conf.getLong("hbase.increasing.policy.initial.size", -1); 060 if (initialSize > 0) { 061 return; 062 } 063 TableDescriptor desc = region.getTableDescriptor(); 064 if (desc != null) { 065 initialSize = 2 * desc.getMemStoreFlushSize(); 066 } 067 if (initialSize <= 0) { 068 initialSize = 2 * conf.getLong(HConstants.HREGION_MEMSTORE_FLUSH_SIZE, 069 TableDescriptorBuilder.DEFAULT_MEMSTORE_FLUSH_SIZE); 070 } 071 } 072 073 @Override 074 protected boolean shouldSplit() { 075 if (!canSplit()) { 076 return false; 077 } 078 // Get count of regions that have the same common table as this.region 079 int tableRegionsCount = getCountOfCommonTableRegions(); 080 // Get size to check 081 long sizeToCheck = getSizeToCheck(tableRegionsCount); 082 boolean shouldSplit = isExceedSize(sizeToCheck); 083 if (shouldSplit) { 084 LOG.debug("regionsWithCommonTable={}", tableRegionsCount); 085 } 086 return shouldSplit; 087 } 088 089 /** Returns Count of regions on this server that share the table this.region belongs to */ 090 private int getCountOfCommonTableRegions() { 091 RegionServerServices rss = region.getRegionServerServices(); 092 // Can be null in tests 093 if (rss == null) { 094 return 0; 095 } 096 TableName tablename = region.getTableDescriptor().getTableName(); 097 int tableRegionsCount = 0; 098 try { 099 List<? extends Region> hri = rss.getRegions(tablename); 100 tableRegionsCount = hri == null || hri.isEmpty() ? 0 : hri.size(); 101 } catch (IOException e) { 102 LOG.debug("Failed getOnlineRegions " + tablename, e); 103 } 104 return tableRegionsCount; 105 } 106 107 /** 108 * @return Region max size or {@code count of regions cubed * 2 * flushsize}, which ever is 109 * smaller; guard against there being zero regions on this server. 110 */ 111 protected long getSizeToCheck(final int tableRegionsCount) { 112 // safety check for 100 to avoid numerical overflow in extreme cases 113 return tableRegionsCount == 0 || tableRegionsCount > 100 114 ? getDesiredMaxFileSize() 115 : Math.min(getDesiredMaxFileSize(), 116 initialSize * tableRegionsCount * tableRegionsCount * tableRegionsCount); 117 } 118 119}