Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 0A578200CA9 for ; Fri, 16 Jun 2017 17:00:40 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id 090C8160BF3; Fri, 16 Jun 2017 15:00:40 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id AEABB160BDD for ; Fri, 16 Jun 2017 17:00:37 +0200 (CEST) Received: (qmail 12932 invoked by uid 500); 16 Jun 2017 15:00:33 -0000 Mailing-List: contact commits-help@hbase.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@hbase.apache.org Delivered-To: mailing list commits@hbase.apache.org Received: (qmail 7924 invoked by uid 99); 16 Jun 2017 15:00:29 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 16 Jun 2017 15:00:29 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 93010F17F6; Fri, 16 Jun 2017 15:00:28 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: git-site-role@apache.org To: commits@hbase.apache.org Date: Fri, 16 Jun 2017 15:00:58 -0000 Message-Id: In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [32/49] hbase-site git commit: Published site at 82d554e3783372cc6b05489452c815b57c06f6cd. archived-at: Fri, 16 Jun 2017 15:00:40 -0000 http://git-wip-us.apache.org/repos/asf/hbase-site/blob/cd7ae54c/devapidocs/src-html/org/apache/hadoop/hbase/master/assignment/SplitTableRegionProcedure.html ---------------------------------------------------------------------- diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/master/assignment/SplitTableRegionProcedure.html b/devapidocs/src-html/org/apache/hadoop/hbase/master/assignment/SplitTableRegionProcedure.html index 6318095..30168b3 100644 --- a/devapidocs/src-html/org/apache/hadoop/hbase/master/assignment/SplitTableRegionProcedure.html +++ b/devapidocs/src-html/org/apache/hadoop/hbase/master/assignment/SplitTableRegionProcedure.html @@ -33,719 +33,735 @@ 025import java.io.InputStream; 026import java.io.InterruptedIOException; 027import java.io.OutputStream; -028import java.util.ArrayList; -029import java.util.Arrays; -030import java.util.Collection; -031import java.util.List; -032import java.util.concurrent.Callable; -033import java.util.concurrent.ExecutionException; -034import java.util.concurrent.ExecutorService; -035import java.util.concurrent.Executors; -036import java.util.concurrent.Future; -037import java.util.concurrent.TimeUnit; -038 -039import org.apache.commons.logging.Log; -040import org.apache.commons.logging.LogFactory; -041import org.apache.hadoop.conf.Configuration; -042import org.apache.hadoop.fs.FileSystem; -043import org.apache.hadoop.fs.Path; -044import org.apache.hadoop.hbase.DoNotRetryIOException; -045import org.apache.hadoop.hbase.HColumnDescriptor; -046import org.apache.hadoop.hbase.HConstants; -047import org.apache.hadoop.hbase.HRegionInfo; -048import org.apache.hadoop.hbase.ServerName; -049import org.apache.hadoop.hbase.TableName; -050import org.apache.hadoop.hbase.classification.InterfaceAudience; -051import org.apache.hadoop.hbase.client.MasterSwitchType; -052import org.apache.hadoop.hbase.client.Mutation; -053import org.apache.hadoop.hbase.client.RegionReplicaUtil; -054import org.apache.hadoop.hbase.client.TableDescriptor; -055import org.apache.hadoop.hbase.io.hfile.CacheConfig; -056import org.apache.hadoop.hbase.master.MasterCoprocessorHost; -057import org.apache.hadoop.hbase.master.MasterFileSystem; -058import org.apache.hadoop.hbase.master.RegionState.State; -059import org.apache.hadoop.hbase.master.assignment.RegionStates.RegionStateNode; -060import org.apache.hadoop.hbase.master.procedure.AbstractStateMachineRegionProcedure; -061import org.apache.hadoop.hbase.master.procedure.MasterProcedureEnv; -062import org.apache.hadoop.hbase.master.procedure.MasterProcedureUtil; -063import org.apache.hadoop.hbase.procedure2.ProcedureMetrics; -064import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos; -065import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos.SplitTableRegionState; -066import org.apache.hadoop.hbase.regionserver.HRegionFileSystem; -067import org.apache.hadoop.hbase.regionserver.HStore; -068import org.apache.hadoop.hbase.regionserver.HStoreFile; -069import org.apache.hadoop.hbase.regionserver.StoreFile; -070import org.apache.hadoop.hbase.regionserver.StoreFileInfo; -071import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetRegionInfoResponse; -072import org.apache.hadoop.hbase.util.Bytes; -073import org.apache.hadoop.hbase.util.EnvironmentEdgeManager; -074import org.apache.hadoop.hbase.util.FSUtils; -075import org.apache.hadoop.hbase.util.Pair; -076import org.apache.hadoop.hbase.util.Threads; -077 -078/** -079 * The procedure to split a region in a table. -080 * Takes lock on the parent region. -081 * It holds the lock for the life of the procedure. -082 */ -083@InterfaceAudience.Private -084public class SplitTableRegionProcedure -085 extends AbstractStateMachineRegionProcedure<SplitTableRegionState> { -086 private static final Log LOG = LogFactory.getLog(SplitTableRegionProcedure.class); -087 private Boolean traceEnabled = null; -088 private HRegionInfo daughter_1_HRI; -089 private HRegionInfo daughter_2_HRI; -090 -091 public SplitTableRegionProcedure() { -092 // Required by the Procedure framework to create the procedure on replay -093 } -094 -095 public SplitTableRegionProcedure(final MasterProcedureEnv env, -096 final HRegionInfo regionToSplit, final byte[] splitRow) throws IOException { -097 super(env, regionToSplit); -098 -099 checkSplitRow(regionToSplit, splitRow); -100 -101 final TableName table = regionToSplit.getTable(); -102 final long rid = getDaughterRegionIdTimestamp(regionToSplit); -103 this.daughter_1_HRI = new HRegionInfo(table, regionToSplit.getStartKey(), splitRow, false, rid); -104 this.daughter_2_HRI = new HRegionInfo(table, splitRow, regionToSplit.getEndKey(), false, rid); -105 } -106 -107 private static void checkSplitRow(final HRegionInfo regionToSplit, final byte[] splitRow) -108 throws IOException { -109 if (splitRow == null || splitRow.length == 0) { -110 throw new DoNotRetryIOException("Split row cannot be null"); -111 } -112 -113 if (Bytes.equals(regionToSplit.getStartKey(), splitRow)) { -114 throw new DoNotRetryIOException( -115 "Split row is equal to startkey: " + Bytes.toStringBinary(splitRow)); -116 } -117 -118 if (!regionToSplit.containsRow(splitRow)) { -119 throw new DoNotRetryIOException( -120 "Split row is not inside region key range splitKey:" + Bytes.toStringBinary(splitRow) + -121 " region: " + regionToSplit); -122 } -123 } -124 -125 /** -126 * Calculate daughter regionid to use. -127 * @param hri Parent {@link HRegionInfo} -128 * @return Daughter region id (timestamp) to use. -129 */ -130 private static long getDaughterRegionIdTimestamp(final HRegionInfo hri) { -131 long rid = EnvironmentEdgeManager.currentTime(); -132 // Regionid is timestamp. Can't be less than that of parent else will insert -133 // at wrong location in hbase:meta (See HBASE-710). -134 if (rid < hri.getRegionId()) { -135 LOG.warn("Clock skew; parent regions id is " + hri.getRegionId() + -136 " but current time here is " + rid); -137 rid = hri.getRegionId() + 1; -138 } -139 return rid; -140 } -141 -142 @Override -143 protected Flow executeFromState(final MasterProcedureEnv env, final SplitTableRegionState state) -144 throws InterruptedException { -145 if (isTraceEnabled()) { -146 LOG.trace(this + " execute state=" + state); -147 } -148 -149 try { -150 switch (state) { -151 case SPLIT_TABLE_REGION_PREPARE: -152 if (prepareSplitRegion(env)) { -153 setNextState(SplitTableRegionState.SPLIT_TABLE_REGION_PRE_OPERATION); -154 break; -155 } else { -156 assert isFailed() : "split region should have an exception here"; -157 return Flow.NO_MORE_STATE; -158 } -159 case SPLIT_TABLE_REGION_PRE_OPERATION: -160 preSplitRegion(env); -161 setNextState(SplitTableRegionState.SPLIT_TABLE_REGION_CLOSE_PARENT_REGION); -162 break; -163 case SPLIT_TABLE_REGION_CLOSE_PARENT_REGION: -164 addChildProcedure(createUnassignProcedures(env, getRegionReplication(env))); -165 setNextState(SplitTableRegionState.SPLIT_TABLE_REGION_CREATE_DAUGHTER_REGIONS); -166 break; -167 case SPLIT_TABLE_REGION_CREATE_DAUGHTER_REGIONS: -168 createDaughterRegions(env); -169 setNextState(SplitTableRegionState.SPLIT_TABLE_REGION_PRE_OPERATION_BEFORE_PONR); -170 break; -171 case SPLIT_TABLE_REGION_PRE_OPERATION_BEFORE_PONR: -172 preSplitRegionBeforePONR(env); -173 setNextState(SplitTableRegionState.SPLIT_TABLE_REGION_UPDATE_META); -174 break; -175 case SPLIT_TABLE_REGION_UPDATE_META: -176 updateMetaForDaughterRegions(env); -177 setNextState(SplitTableRegionState.SPLIT_TABLE_REGION_PRE_OPERATION_AFTER_PONR); -178 break; -179 case SPLIT_TABLE_REGION_PRE_OPERATION_AFTER_PONR: -180 preSplitRegionAfterPONR(env); -181 setNextState(SplitTableRegionState.SPLIT_TABLE_REGION_OPEN_CHILD_REGIONS); -182 break; -183 case SPLIT_TABLE_REGION_OPEN_CHILD_REGIONS: -184 addChildProcedure(createAssignProcedures(env, getRegionReplication(env))); -185 setNextState(SplitTableRegionState.SPLIT_TABLE_REGION_POST_OPERATION); -186 break; -187 case SPLIT_TABLE_REGION_POST_OPERATION: -188 postSplitRegion(env); -189 return Flow.NO_MORE_STATE; -190 default: -191 throw new UnsupportedOperationException(this + " unhandled state=" + state); -192 } -193 } catch (IOException e) { -194 String msg = "Error trying to split region " + getParentRegion().getEncodedName() + " in the table " -195 + getTableName() + " (in state=" + state + ")"; -196 if (!isRollbackSupported(state)) { -197 // We reach a state that cannot be rolled back. We just need to keep retry. -198 LOG.warn(msg, e); -199 } else { -200 LOG.error(msg, e); -201 setFailure(e); -202 } -203 } -204 return Flow.HAS_MORE_STATE; -205 } -206 -207 @Override -208 protected void rollbackState(final MasterProcedureEnv env, final SplitTableRegionState state) -209 throws IOException, InterruptedException { -210 if (isTraceEnabled()) { -211 LOG.trace(this + " rollback state=" + state); -212 } -213 -214 try { -215 switch (state) { -216 case SPLIT_TABLE_REGION_POST_OPERATION: -217 case SPLIT_TABLE_REGION_OPEN_CHILD_REGIONS: -218 case SPLIT_TABLE_REGION_PRE_OPERATION_AFTER_PONR: -219 case SPLIT_TABLE_REGION_UPDATE_META: -220 // PONR -221 throw new UnsupportedOperationException(this + " unhandled state=" + state); -222 case SPLIT_TABLE_REGION_PRE_OPERATION_BEFORE_PONR: +028import java.util.*; +029import java.util.concurrent.Callable; +030import java.util.concurrent.ExecutionException; +031import java.util.concurrent.ExecutorService; +032import java.util.concurrent.Executors; +033import java.util.concurrent.Future; +034import java.util.concurrent.TimeUnit; +035 +036import org.apache.commons.logging.Log; +037import org.apache.commons.logging.LogFactory; +038import org.apache.hadoop.conf.Configuration; +039import org.apache.hadoop.fs.FileSystem; +040import org.apache.hadoop.fs.Path; +041import org.apache.hadoop.hbase.DoNotRetryIOException; +042import org.apache.hadoop.hbase.HColumnDescriptor; +043import org.apache.hadoop.hbase.HConstants; +044import org.apache.hadoop.hbase.HRegionInfo; +045import org.apache.hadoop.hbase.ServerName; +046import org.apache.hadoop.hbase.TableName; +047import org.apache.hadoop.hbase.classification.InterfaceAudience; +048import org.apache.hadoop.hbase.client.MasterSwitchType; +049import org.apache.hadoop.hbase.client.Mutation; +050import org.apache.hadoop.hbase.client.RegionReplicaUtil; +051import org.apache.hadoop.hbase.client.TableDescriptor; +052import org.apache.hadoop.hbase.io.hfile.CacheConfig; +053import org.apache.hadoop.hbase.master.MasterCoprocessorHost; +054import org.apache.hadoop.hbase.master.MasterFileSystem; +055import org.apache.hadoop.hbase.master.RegionState.State; +056import org.apache.hadoop.hbase.master.assignment.RegionStates.RegionStateNode; +057import org.apache.hadoop.hbase.master.procedure.AbstractStateMachineRegionProcedure; +058import org.apache.hadoop.hbase.master.procedure.MasterProcedureEnv; +059import org.apache.hadoop.hbase.master.procedure.MasterProcedureUtil; +060import org.apache.hadoop.hbase.procedure2.ProcedureMetrics; +061import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos; +062import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos.SplitTableRegionState; +063import org.apache.hadoop.hbase.regionserver.HRegionFileSystem; +064import org.apache.hadoop.hbase.regionserver.HStore; +065import org.apache.hadoop.hbase.regionserver.HStoreFile; +066import org.apache.hadoop.hbase.regionserver.StoreFile; +067import org.apache.hadoop.hbase.regionserver.StoreFileInfo; +068import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetRegionInfoResponse; +069import org.apache.hadoop.hbase.util.Bytes; +070import org.apache.hadoop.hbase.util.EnvironmentEdgeManager; +071import org.apache.hadoop.hbase.util.FSUtils; +072import org.apache.hadoop.hbase.util.Pair; +073import org.apache.hadoop.hbase.util.Threads; +074 +075/** +076 * The procedure to split a region in a table. +077 * Takes lock on the parent region. +078 * It holds the lock for the life of the procedure. +079 */ +080@InterfaceAudience.Private +081public class SplitTableRegionProcedure +082 extends AbstractStateMachineRegionProcedure<SplitTableRegionState> { +083 private static final Log LOG = LogFactory.getLog(SplitTableRegionProcedure.class); +084 private Boolean traceEnabled = null; +085 private HRegionInfo daughter_1_HRI; +086 private HRegionInfo daughter_2_HRI; +087 +088 public SplitTableRegionProcedure() { +089 // Required by the Procedure framework to create the procedure on replay +090 } +091 +092 public SplitTableRegionProcedure(final MasterProcedureEnv env, +093 final HRegionInfo regionToSplit, final byte[] splitRow) throws IOException { +094 super(env, regionToSplit); +095 +096 checkSplitRow(regionToSplit, splitRow); +097 +098 final TableName table = regionToSplit.getTable(); +099 final long rid = getDaughterRegionIdTimestamp(regionToSplit); +100 this.daughter_1_HRI = new HRegionInfo(table, regionToSplit.getStartKey(), splitRow, false, rid); +101 this.daughter_2_HRI = new HRegionInfo(table, splitRow, regionToSplit.getEndKey(), false, rid); +102 } +103 +104 private static void checkSplitRow(final HRegionInfo regionToSplit, final byte[] splitRow) +105 throws IOException { +106 if (splitRow == null || splitRow.length == 0) { +107 throw new DoNotRetryIOException("Split row cannot be null"); +108 } +109 +110 if (Bytes.equals(regionToSplit.getStartKey(), splitRow)) { +111 throw new DoNotRetryIOException( +112 "Split row is equal to startkey: " + Bytes.toStringBinary(splitRow)); +113 } +114 +115 if (!regionToSplit.containsRow(splitRow)) { +116 throw new DoNotRetryIOException( +117 "Split row is not inside region key range splitKey:" + Bytes.toStringBinary(splitRow) + +118 " region: " + regionToSplit); +119 } +120 } +121 +122 /** +123 * Calculate daughter regionid to use. +124 * @param hri Parent {@link HRegionInfo} +125 * @return Daughter region id (timestamp) to use. +126 */ +127 private static long getDaughterRegionIdTimestamp(final HRegionInfo hri) { +128 long rid = EnvironmentEdgeManager.currentTime(); +129 // Regionid is timestamp. Can't be less than that of parent else will insert +130 // at wrong location in hbase:meta (See HBASE-710). +131 if (rid < hri.getRegionId()) { +132 LOG.warn("Clock skew; parent regions id is " + hri.getRegionId() + +133 " but current time here is " + rid); +134 rid = hri.getRegionId() + 1; +135 } +136 return rid; +137 } +138 +139 @Override +140 protected Flow executeFromState(final MasterProcedureEnv env, final SplitTableRegionState state) +141 throws InterruptedException { +142 if (isTraceEnabled()) { +143 LOG.trace(this + " execute state=" + state); +144 } +145 +146 try { +147 switch (state) { +148 case SPLIT_TABLE_REGION_PREPARE: +149 if (prepareSplitRegion(env)) { +150 setNextState(SplitTableRegionState.SPLIT_TABLE_REGION_PRE_OPERATION); +151 break; +152 } else { +153 assert isFailed() : "split region should have an exception here"; +154 return Flow.NO_MORE_STATE; +155 } +156 case SPLIT_TABLE_REGION_PRE_OPERATION: +157 preSplitRegion(env); +158 setNextState(SplitTableRegionState.SPLIT_TABLE_REGION_CLOSE_PARENT_REGION); +159 break; +160 case SPLIT_TABLE_REGION_CLOSE_PARENT_REGION: +161 addChildProcedure(createUnassignProcedures(env, getRegionReplication(env))); +162 setNextState(SplitTableRegionState.SPLIT_TABLE_REGION_CREATE_DAUGHTER_REGIONS); +163 break; +164 case SPLIT_TABLE_REGION_CREATE_DAUGHTER_REGIONS: +165 createDaughterRegions(env); +166 setNextState(SplitTableRegionState.SPLIT_TABLE_REGION_PRE_OPERATION_BEFORE_PONR); +167 break; +168 case SPLIT_TABLE_REGION_PRE_OPERATION_BEFORE_PONR: +169 preSplitRegionBeforePONR(env); +170 setNextState(SplitTableRegionState.SPLIT_TABLE_REGION_UPDATE_META); +171 break; +172 case SPLIT_TABLE_REGION_UPDATE_META: +173 updateMetaForDaughterRegions(env); +174 setNextState(SplitTableRegionState.SPLIT_TABLE_REGION_PRE_OPERATION_AFTER_PONR); +175 break; +176 case SPLIT_TABLE_REGION_PRE_OPERATION_AFTER_PONR: +177 preSplitRegionAfterPONR(env); +178 setNextState(SplitTableRegionState.SPLIT_TABLE_REGION_OPEN_CHILD_REGIONS); +179 break; +180 case SPLIT_TABLE_REGION_OPEN_CHILD_REGIONS: +181 addChildProcedure(createAssignProcedures(env, getRegionReplication(env))); +182 setNextState(SplitTableRegionState.SPLIT_TABLE_REGION_POST_OPERATION); +183 break; +184 case SPLIT_TABLE_REGION_POST_OPERATION: +185 postSplitRegion(env); +186 return Flow.NO_MORE_STATE; +187 default: +188 throw new UnsupportedOperationException(this + " unhandled state=" + state); +189 } +190 } catch (IOException e) { +191 String msg = "Error trying to split region " + getParentRegion().getEncodedName() + " in the table " +192 + getTableName() + " (in state=" + state + ")"; +193 if (!isRollbackSupported(state)) { +194 // We reach a state that cannot be rolled back. We just need to keep retry. +195 LOG.warn(msg, e); +196 } else { +197 LOG.error(msg, e); +198 setFailure(e); +199 } +200 } +201 return Flow.HAS_MORE_STATE; +202 } +203 +204 @Override +205 protected void rollbackState(final MasterProcedureEnv env, final SplitTableRegionState state) +206 throws IOException, InterruptedException { +207 if (isTraceEnabled()) { +208 LOG.trace(this + " rollback state=" + state); +209 } +210 +211 try { +212 switch (state) { +213 case SPLIT_TABLE_REGION_POST_OPERATION: +214 case SPLIT_TABLE_REGION_OPEN_CHILD_REGIONS: +215 case SPLIT_TABLE_REGION_PRE_OPERATION_AFTER_PONR: +216 case SPLIT_TABLE_REGION_UPDATE_META: +217 // PONR +218 throw new UnsupportedOperationException(this + " unhandled state=" + state); +219 case SPLIT_TABLE_REGION_PRE_OPERATION_BEFORE_PONR: +220 break; +221 case SPLIT_TABLE_REGION_CREATE_DAUGHTER_REGIONS: +222 // Doing nothing, as re-open parent region would clean up daughter region directories. 223 break; -224 case SPLIT_TABLE_REGION_CREATE_DAUGHTER_REGIONS: -225 // Doing nothing, as re-open parent region would clean up daughter region directories. +224 case SPLIT_TABLE_REGION_CLOSE_PARENT_REGION: +225 openParentRegion(env); 226 break; -227 case SPLIT_TABLE_REGION_CLOSE_PARENT_REGION: -228 openParentRegion(env); +227 case SPLIT_TABLE_REGION_PRE_OPERATION: +228 postRollBackSplitRegion(env); 229 break; -230 case SPLIT_TABLE_REGION_PRE_OPERATION: -231 postRollBackSplitRegion(env); -232 break; -233 case SPLIT_TABLE_REGION_PREPARE: -234 break; // nothing to do -235 default: -236 throw new UnsupportedOperationException(this + " unhandled state=" + state); -237 } -238 } catch (IOException e) { -239 // This will be retried. Unless there is a bug in the code, -240 // this should be just a "temporary error" (e.g. network down) -241 LOG.warn("pid=" + getProcId() + " failed rollback attempt step " + state + -242 " for splitting the region " -243 + getParentRegion().getEncodedName() + " in table " + getTableName(), e); -244 throw e; -245 } -246 } -247 -248 /* -249 * Check whether we are in the state that can be rollback -250 */ -251 @Override -252 protected boolean isRollbackSupported(final SplitTableRegionState state) { -253 switch (state) { -254 case SPLIT_TABLE_REGION_POST_OPERATION: -255 case SPLIT_TABLE_REGION_OPEN_CHILD_REGIONS: -256 case SPLIT_TABLE_REGION_PRE_OPERATION_AFTER_PONR: -257 case SPLIT_TABLE_REGION_UPDATE_META: -258 // It is not safe to rollback if we reach to these states. -259 return false; -260 default: -261 break; -262 } -263 return true; -264 } -265 -266 @Override -267 protected SplitTableRegionState getState(final int stateId) { -268 return SplitTableRegionState.forNumber(stateId); -269 } -270 -271 @Override -272 protected int getStateId(final SplitTableRegionState state) { -273 return state.getNumber(); -274 } -275 -276 @Override -277 protected SplitTableRegionState getInitialState() { -278 return SplitTableRegionState.SPLIT_TABLE_REGION_PREPARE; -279 } -280 -281 @Override -282 public void serializeStateData(final OutputStream stream) throws IOException { -283 super.serializeStateData(stream); -284 -285 final MasterProcedureProtos.SplitTableRegionStateData.Builder splitTableRegionMsg = -286 MasterProcedureProtos.SplitTableRegionStateData.newBuilder() -287 .setUserInfo(MasterProcedureUtil.toProtoUserInfo(getUser())) -288 .setParentRegionInfo(HRegionInfo.convert(getRegion())) -289 .addChildRegionInfo(HRegionInfo.convert(daughter_1_HRI)) -290 .addChildRegionInfo(HRegionInfo.convert(daughter_2_HRI)); -291 splitTableRegionMsg.build().writeDelimitedTo(stream); -292 } -293 -294 @Override -295 public void deserializeStateData(final InputStream stream) throws IOException { -296 super.deserializeStateData(stream); -297 -298 final MasterProcedureProtos.SplitTableRegionStateData splitTableRegionsMsg = -299 MasterProcedureProtos.SplitTableRegionStateData.parseDelimitedFrom(stream); -300 setUser(MasterProcedureUtil.toUserInfo(splitTableRegionsMsg.getUserInfo())); -301 setRegion(HRegionInfo.convert(splitTableRegionsMsg.getParentRegionInfo())); -302 assert(splitTableRegionsMsg.getChildRegionInfoCount() == 2); -303 daughter_1_HRI = HRegionInfo.convert(splitTableRegionsMsg.getChildRegionInfo(0)); -304 daughter_2_HRI = HRegionInfo.convert(splitTableRegionsMsg.getChildRegionInfo(1)); -305 } -306 -307 @Override -308 public void toStringClassDetails(StringBuilder sb) { -309 sb.append(getClass().getSimpleName()); -310 sb.append(" table="); -311 sb.append(getTableName()); -312 sb.append(", parent="); -313 sb.append(getParentRegion().getShortNameToLog()); -314 sb.append(", daughterA="); -315 sb.append(daughter_1_HRI.getShortNameToLog()); -316 sb.append(", daughterB="); -317 sb.append(daughter_2_HRI.getShortNameToLog()); -318 } -319 -320 private HRegionInfo getParentRegion() { -321 return getRegion(); -322 } -323 -324 @Override -325 public TableOperationType getTableOperationType() { -326 return TableOperationType.REGION_SPLIT; -327 } -328 -329 @Override -330 protected ProcedureMetrics getProcedureMetrics(MasterProcedureEnv env) { -331 return env.getAssignmentManager().getAssignmentManagerMetrics().getSplitProcMetrics(); -332 } -333 -334 private byte[] getSplitRow() { -335 return daughter_2_HRI.getStartKey(); -336 } -337 -338 private static State [] EXPECTED_SPLIT_STATES = new State [] {State.OPEN, State.CLOSED}; -339 /** -340 * Prepare to Split region. -341 * @param env MasterProcedureEnv -342 * @throws IOException -343 */ -344 @VisibleForTesting -345 public boolean prepareSplitRegion(final MasterProcedureEnv env) throws IOException { -346 // Check whether the region is splittable -347 RegionStateNode node = -348 env.getAssignmentManager().getRegionStates().getRegionNode(getParentRegion()); -349 HRegionInfo parentHRI = null; -350 if (node != null) { -351 parentHRI = node.getRegionInfo(); -352 -353 // Lookup the parent HRI state from the AM, which has the latest updated info. -354 // Protect against the case where concurrent SPLIT requests came in and succeeded -355 // just before us. -356 if (node.isInState(State.SPLIT)) { -357 LOG.info("Split of " + parentHRI + " skipped; state is already SPLIT"); -358 return false; -359 } -360 if (parentHRI.isSplit() || parentHRI.isOffline()) { -361 LOG.info("Split of " + parentHRI + " skipped because offline/split."); -362 return false; -363 } -364 -365 // expected parent to be online or closed -366 if (!node.isInState(EXPECTED_SPLIT_STATES)) { -367 // We may have SPLIT already? -368 setFailure(new IOException("Split " + parentHRI.getRegionNameAsString() + -369 " FAILED because state=" + node.getState() + "; expected " + -370 Arrays.toString(EXPECTED_SPLIT_STATES))); -371 return false; -372 } -373 -374 // Ask the remote regionserver if this region is splittable. If we get an IOE, report it -375 // along w/ the failure so can see why we are not splittable at this time. -376 IOException splittableCheckIOE = null; -377 boolean splittable = false; -378 try { -379 GetRegionInfoResponse response = -380 Util.getRegionInfoResponse(env, node.getRegionLocation(), node.getRegionInfo()); -381 splittable = response.hasSplittable() && response.getSplittable(); -382 if (LOG.isDebugEnabled()) { -383 LOG.debug("Splittable=" + splittable + " " + this + " " + node.toShortString()); -384 } -385 } catch (IOException e) { -386 splittableCheckIOE = e; -387 } -388 if (!splittable) { -389 IOException e = new IOException(parentHRI.getShortNameToLog() + " NOT splittable"); -390 if (splittableCheckIOE != null) e.initCause(splittableCheckIOE); -391 setFailure(e); -392 return false; -393 } -394 } -395 -396 // Since we have the lock and the master is coordinating the operation -397 // we are always able to split the region -398 if (!env.getMasterServices().isSplitOrMergeEnabled(MasterSwitchType.SPLIT)) { -399 LOG.warn("pid=" + getProcId() + " split switch is off! skip split of " + parentHRI); -400 setFailure(new IOException("Split region " + -401 (parentHRI == null? "null": parentHRI.getRegionNameAsString()) + -402 " failed due to split switch off")); -403 return false; -404 } -405 return true; -406 } -407 -408 /** -409 * Action before splitting region in a table. -410 * @param env MasterProcedureEnv -411 * @param state the procedure state -412 * @throws IOException -413 * @throws InterruptedException -414 */ -415 private void preSplitRegion(final MasterProcedureEnv env) -416 throws IOException, InterruptedException { -417 final MasterCoprocessorHost cpHost = env.getMasterCoprocessorHost(); -418 if (cpHost != null) { -419 cpHost.preSplitRegionAction(getTableName(), getSplitRow(), getUser()); -420 } -421 } -422 -423 /** -424 * Action after rollback a split table region action. -425 * @param env MasterProcedureEnv -426 * @throws IOException -427 */ -428 private void postRollBackSplitRegion(final MasterProcedureEnv env) throws IOException { -429 final MasterCoprocessorHost cpHost = env.getMasterCoprocessorHost(); -430 if (cpHost != null) { -431 cpHost.postRollBackSplitRegionAction(getUser()); -432 } -433 } -434 -435 /** -436 * Rollback close parent region -437 * @param env MasterProcedureEnv -438 **/ -439 private void openParentRegion(final MasterProcedureEnv env) throws IOException { -440 // Check whether the region is closed; if so, open it in the same server -441 final int regionReplication = getRegionReplication(env); -442 final ServerName serverName = getParentRegionServerName(env); -443 -444 final AssignProcedure[] procs = new AssignProcedure[regionReplication]; -445 for (int i = 0; i < regionReplication; ++i) { -446 final HRegionInfo hri = RegionReplicaUtil.getRegionInfoForReplica(getParentRegion(), i); -447 procs[i] = env.getAssignmentManager().createAssignProcedure(hri, serverName); -448 } -449 env.getMasterServices().getMasterProcedureExecutor().submitProcedures(procs); -450 } -451 -452 /** -453 * Create daughter regions -454 * @param env MasterProcedureEnv -455 * @throws IOException -456 */ -457 @VisibleForTesting -458 public void createDaughterRegions(final MasterProcedureEnv env) throws IOException { -459 final MasterFileSystem mfs = env.getMasterServices().getMasterFileSystem(); -460 final Path tabledir = FSUtils.getTableDir(mfs.getRootDir(), getTableName()); -461 final FileSystem fs = mfs.getFileSystem(); -462 HRegionFileSystem regionFs = HRegionFileSystem.openRegionFromFileSystem( -463 env.getMasterConfiguration(), fs, tabledir, getParentRegion(), false); -464 regionFs.createSplitsDir(); -465 -466 Pair<Integer, Integer> expectedReferences = splitStoreFiles(env, regionFs); -467 +230 case SPLIT_TABLE_REGION_PREPARE: +231 break; // nothing to do +232 default: +233 throw new UnsupportedOperationException(this + " unhandled state=" + state); +234 } +235 } catch (IOException e) { +236 // This will be retried. Unless there is a bug in the code, +237 // this should be just a "temporary error" (e.g. network down) +238 LOG.warn("pid=" + getProcId() + " failed rollback attempt step " + state + +239 " for splitting the region " +240 + getParentRegion().getEncodedName() + " in table " + getTableName(), e); +241 throw e; +242 } +243 } +244 +245 /* +246 * Check whether we are in the state that can be rollback +247 */ +248 @Override +249 protected boolean isRollbackSupported(final SplitTableRegionState state) { +250 switch (state) { +251 case SPLIT_TABLE_REGION_POST_OPERATION: +252 case SPLIT_TABLE_REGION_OPEN_CHILD_REGIONS: +253 case SPLIT_TABLE_REGION_PRE_OPERATION_AFTER_PONR: +254 case SPLIT_TABLE_REGION_UPDATE_META: +255 // It is not safe to rollback if we reach to these states. +256 return false; +257 default: +258 break; +259 } +260 return true; +261 } +262 +263 @Override +264 protected SplitTableRegionState getState(final int stateId) { +265 return SplitTableRegionState.forNumber(stateId); +266 } +267 +268 @Override +269 protected int getStateId(final SplitTableRegionState state) { +270 return state.getNumber(); +271 } +272 +273 @Override +274 protected SplitTableRegionState getInitialState() { +275 return SplitTableRegionState.SPLIT_TABLE_REGION_PREPARE; +276 } +277 +278 @Override +279 public void serializeStateData(final OutputStream stream) throws IOException { +280 super.serializeStateData(stream); +281 +282 final MasterProcedureProtos.SplitTableRegionStateData.Builder splitTableRegionMsg = +283 MasterProcedureProtos.SplitTableRegionStateData.newBuilder() +284 .setUserInfo(MasterProcedureUtil.toProtoUserInfo(getUser())) +285 .setParentRegionInfo(HRegionInfo.convert(getRegion())) +286 .addChildRegionInfo(HRegionInfo.convert(daughter_1_HRI)) +287 .addChildRegionInfo(HRegionInfo.convert(daughter_2_HRI)); +288 splitTableRegionMsg.build().writeDelimitedTo(stream); +289 } +290 +291 @Override +292 public void deserializeStateData(final InputStream stream) throws IOException { +293 super.deserializeStateData(stream); +294 +295 final MasterProcedureProtos.SplitTableRegionStateData splitTableRegionsMsg = +296 MasterProcedureProtos.SplitTableRegionStateData.parseDelimitedFrom(stream); +297 setUser(MasterProcedureUtil.toUserInfo(splitTableRegionsMsg.getUserInfo())); +298 setRegion(HRegionInfo.convert(splitTableRegionsMsg.getParentRegionInfo())); +299 assert(splitTableRegionsMsg.getChildRegionInfoCount() == 2); +300 daughter_1_HRI = HRegionInfo.convert(splitTableRegionsMsg.getChildRegionInfo(0)); +301 daughter_2_HRI = HRegionInfo.convert(splitTableRegionsMsg.getChildRegionInfo(1)); +302 } +303 +304 @Override +305 public void toStringClassDetails(StringBuilder sb) { +306 sb.append(getClass().getSimpleName()); +307 sb.append(" table="); +308 sb.append(getTableName()); +309 sb.append(", parent="); +310 sb.append(getParentRegion().getShortNameToLog()); +311 sb.append(", daughterA="); +312 sb.append(daughter_1_HRI.getShortNameToLog()); +313 sb.append(", daughterB="); +314 sb.append(daughter_2_HRI.getShortNameToLog()); +315 } +316 +317 private HRegionInfo getParentRegion() { +318 return getRegion(); +319 } +320 +321 @Override +322 public TableOperationType getTableOperationType() { +323 return TableOperationType.REGION_SPLIT; +324 } +325 +326 @Override +327 protected ProcedureMetrics getProcedureMetrics(MasterProcedureEnv env) { +328 return env.getAssignmentManager().getAssignmentManagerMetrics().getSplitProcMetrics(); +329 } +330 +331 private byte[] getSplitRow() { +332 return daughter_2_HRI.getStartKey(); +333 } +334 +335 private static State [] EXPECTED_SPLIT_STATES = new State [] {State.OPEN, State.CLOSED}; +336 /** +337 * Prepare to Split region. +338 * @param env MasterProcedureEnv +339 * @throws IOException +340 */ +341 @VisibleForTesting +342 public boolean prepareSplitRegion(final MasterProcedureEnv env) throws IOException { +343 // Check whether the region is splittable +344 RegionStateNode node = +345 env.getAssignmentManager().getRegionStates().getRegionNode(getParentRegion()); +346 HRegionInfo parentHRI = null; +347 if (node != null) { +348 parentHRI = node.getRegionInfo(); +349 +350 // Lookup the parent HRI state from the AM, which has the latest updated info. +351 // Protect against the case where concurrent SPLIT requests came in and succeeded +352 // just before us. +353 if (node.isInState(State.SPLIT)) { +354 LOG.info("Split of " + parentHRI + " skipped; state is already SPLIT"); +355 return false; +356 } +357 if (parentHRI.isSplit() || parentHRI.isOffline()) { +358 LOG.info("Split of " + parentHRI + " skipped because offline/split."); +359 return false; +360 } +361 +362 // expected parent to be online or closed +363 if (!node.isInState(EXPECTED_SPLIT_STATES)) { +364 // We may have SPLIT already? +365 setFailure(new IOException("Split " + parentHRI.getRegionNameAsString() + +366 " FAILED because state=" + node.getState() + "; expected " + +367 Arrays.toString(EXPECTED_SPLIT_STATES))); +368 return false; +369 } +370 +371 // Ask the remote regionserver if this region is splittable. If we get an IOE, report it +372 // along w/ the failure so can see why we are not splittable at this time. +373 IOException splittableCheckIOE = null; +374 boolean splittable = false; +375 try { +376 GetRegionInfoResponse response = +377 Util.getRegionInfoResponse(env, node.getRegionLocation(), node.getRegionInfo()); +378 splittable = response.hasSplittable() && response.getSplittable(); +379 if (LOG.isDebugEnabled()) { +380 LOG.debug("Splittable=" + splittable + " " + this + " " + node.toShortString()); +381 } +382 } catch (IOException e) { +383 splittableCheckIOE = e; +384 } +385 if (!splittable) { +386 IOException e = new IOException(parentHRI.getShortNameToLog() + " NOT splittable"); +387 if (splittableCheckIOE != null) e.initCause(splittableCheckIOE); +388 setFailure(e); +389 return false; +390 } +391 } +392 +393 // Since we have the lock and the master is coordinating the operation +394 // we are always able to split the region +395 if (!env.getMasterServices().isSplitOrMergeEnabled(MasterSwitchType.SPLIT)) { +396 LOG.warn("pid=" + getProcId() + " split switch is off! skip split of " + parentHRI); +397 setFailure(new IOException("Split region " + +398 (parentHRI == null? "null": parentHRI.getRegionNameAsString()) + +399 " failed due to split switch off")); +400 return false; +401 } +402 return true; +403 } +404 +405 /** +406 * Action before splitting region in a table. +407 * @param env MasterProcedureEnv +408 * @throws IOException +409 * @throws InterruptedException +410 */ +411 private void preSplitRegion(final MasterProcedureEnv env) +412 throws IOException, InterruptedException { +413 final MasterCoprocessorHost cpHost = env.getMasterCoprocessorHost(); +414 if (cpHost != null) { +415 cpHost.preSplitRegionAction(getTableName(), getSplitRow(), getUser()); +416 } +417 } +418 +419 /** +420 * Action after rollback a split table region action. +421 * @param env MasterProcedureEnv +422 * @throws IOException +423 */ +424 private void postRollBackSplitRegion(final MasterProcedureEnv env) throws IOException { +425 final MasterCoprocessorHost cpHost = env.getMasterCoprocessorHost(); +426 if (cpHost != null) { +427 cpHost.postRollBackSplitRegionAction(getUser()); +428 } +429 } +430 +431 /** +432 * Rollback close parent region +433 * @param env MasterProcedureEnv +434 **/ +435 private void openParentRegion(final MasterProcedureEnv env) throws IOException { +436 // Check whether the region is closed; if so, open it in the same server +437 final int regionReplication = getRegionReplication(env); +438 final ServerName serverName = getParentRegionServerName(env); +439 +440 final AssignProcedure[] procs = new AssignProcedure[regionReplication]; +441 for (int i = 0; i < regionReplication; ++i) { +442 final HRegionInfo hri = RegionReplicaUtil.getRegionInfoForReplica(getParentRegion(), i); +443 procs[i] = env.getAssignmentManager().createAssignProcedure(hri, serverName); +444 } +445 env.getMasterServices().getMasterProcedureExecutor().submitProcedures(procs); +446 } +447 +448 /** +449 * Create daughter regions +450 * @param env MasterProcedureEnv +451 * @throws IOException +452 */ +453 @VisibleForTesting +454 public void createDaughterRegions(final MasterProcedureEnv env) throws IOException { +455 final MasterFileSystem mfs = env.getMasterServices().getMasterFileSystem(); +456 final Path tabledir = FSUtils.getTableDir(mfs.getRootDir(), getTableName()); +457 final FileSystem fs = mfs.getFileSystem(); +458 HRegionFileSystem regionFs = HRegionFileSystem.openRegionFromFileSystem( +459 env.getMasterConfiguration(), fs, tabledir, getParentRegion(), false); +460 regionFs.createSplitsDir(); +461 +462 Pair<Integer, Integer> expectedReferences = splitStoreFiles(env, regionFs); +463 +464 assertReferenceFileCount(fs, expectedReferences.getFirst(), +465 regionFs.getSplitsDir(daughter_1_HRI)); +466 //Move the files from the temporary .splits to the final /table/region directory +467 regionFs.commitDaughterRegion(daughter_1_HRI); 468 assertReferenceF