001/** 002 * 003 * Licensed to the Apache Software Foundation (ASF) under one 004 * or more contributor license agreements. See the NOTICE file 005 * distributed with this work for additional information 006 * regarding copyright ownership. The ASF licenses this file 007 * to you under the Apache License, Version 2.0 (the 008 * "License"); you may not use this file except in compliance 009 * with the License. You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, software 014 * distributed under the License is distributed on an "AS IS" BASIS, 015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 */ 019package org.apache.hadoop.hbase.regionserver; 020 021import java.security.PrivilegedAction; 022import org.apache.hadoop.hbase.HConstants; 023import org.apache.hadoop.hbase.TableName; 024import org.apache.hadoop.hbase.client.RegionInfo; 025import org.apache.hadoop.hbase.client.RegionInfoBuilder; 026import org.apache.hadoop.hbase.regionserver.RegionServerServices.RegionStateTransitionContext; 027import org.apache.hadoop.hbase.security.User; 028import org.apache.hadoop.hbase.util.Bytes; 029import org.apache.yetus.audience.InterfaceAudience; 030import org.slf4j.Logger; 031import org.slf4j.LoggerFactory; 032 033import org.apache.hbase.thirdparty.com.google.common.base.Preconditions; 034 035import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.RegionStateTransition.TransitionCode; 036 037/** 038 * Handles processing region splits. Put in a queue, owned by HRegionServer. 039 */ 040@InterfaceAudience.Private 041class SplitRequest implements Runnable { 042 private static final Logger LOG = LoggerFactory.getLogger(SplitRequest.class); 043 private final RegionInfo parent; 044 private final byte[] midKey; 045 private final HRegionServer server; 046 private final User user; 047 048 SplitRequest(Region region, byte[] midKey, HRegionServer hrs, User user) { 049 Preconditions.checkNotNull(hrs); 050 this.parent = region.getRegionInfo(); 051 this.midKey = midKey; 052 this.server = hrs; 053 this.user = user; 054 } 055 056 @Override 057 public String toString() { 058 return "regionName=" + parent + ", midKey=" + Bytes.toStringBinary(midKey); 059 } 060 061 private void doSplitting() { 062 server.getMetrics().incrSplitRequest(); 063 if (user != null && user.getUGI() != null) { 064 user.getUGI().doAs((PrivilegedAction<Void>) () -> { 065 requestRegionSplit(); 066 return null; 067 }); 068 } else { 069 requestRegionSplit(); 070 } 071 } 072 073 private void requestRegionSplit() { 074 final TableName table = parent.getTable(); 075 final RegionInfo hri_a = RegionInfoBuilder.newBuilder(table) 076 .setStartKey(parent.getStartKey()) 077 .setEndKey(midKey) 078 .build(); 079 final RegionInfo hri_b = RegionInfoBuilder.newBuilder(table) 080 .setStartKey(midKey) 081 .setEndKey(parent.getEndKey()) 082 .build(); 083 // Send the split request to the master. the master will do the validation on the split-key. 084 // The parent region will be unassigned and the two new regions will be assigned. 085 // hri_a and hri_b objects may not reflect the regions that will be created, those objects 086 // are created just to pass the information to the reportRegionStateTransition(). 087 if (!server.reportRegionStateTransition(new RegionStateTransitionContext( 088 TransitionCode.READY_TO_SPLIT, HConstants.NO_SEQNUM, -1, parent, hri_a, hri_b))) { 089 LOG.error("Unable to ask master to split " + parent.getRegionNameAsString()); 090 } 091 } 092 093 @Override 094 public void run() { 095 if (this.server.isStopping() || this.server.isStopped()) { 096 LOG.debug("Skipping split because server is stopping=" + 097 this.server.isStopping() + " or stopped=" + this.server.isStopped()); 098 return; 099 } 100 101 doSplitting(); 102 } 103}