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.master.assignment;
019
020import java.io.IOException;
021import org.apache.hadoop.hbase.ServerName;
022import org.apache.hadoop.hbase.client.RegionInfo;
023import org.apache.hadoop.hbase.exceptions.UnexpectedStateException;
024import org.apache.hadoop.hbase.master.RegionState.State;
025import org.apache.hadoop.hbase.master.procedure.MasterProcedureEnv;
026import org.apache.hadoop.hbase.master.procedure.RSProcedureDispatcher.RegionOpenOperation;
027import org.apache.hadoop.hbase.procedure2.ProcedureMetrics;
028import org.apache.hadoop.hbase.procedure2.ProcedureStateSerializer;
029import org.apache.hadoop.hbase.procedure2.RemoteProcedureDispatcher.RemoteOperation;
030import org.apache.yetus.audience.InterfaceAudience;
031import org.slf4j.Logger;
032import org.slf4j.LoggerFactory;
033
034import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos.OpenRegionProcedureStateData;
035import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.RegionStateTransition.TransitionCode;
036
037/**
038 * The remote procedure used to open a region.
039 */
040@InterfaceAudience.Private
041public class OpenRegionProcedure extends RegionRemoteProcedureBase {
042
043  private static final Logger LOG = LoggerFactory.getLogger(OpenRegionProcedure.class);
044
045  public OpenRegionProcedure() {
046    super();
047  }
048
049  public OpenRegionProcedure(TransitRegionStateProcedure parent, RegionInfo region,
050      ServerName targetServer) {
051    super(parent, region, targetServer);
052  }
053
054  @Override
055  public TableOperationType getTableOperationType() {
056    return TableOperationType.REGION_ASSIGN;
057  }
058
059  @Override
060  public RemoteOperation newRemoteOperation() {
061    return new RegionOpenOperation(this, region, getProcId());
062  }
063
064  @Override
065  protected void serializeStateData(ProcedureStateSerializer serializer) throws IOException {
066    super.serializeStateData(serializer);
067    serializer.serialize(OpenRegionProcedureStateData.getDefaultInstance());
068  }
069
070  @Override
071  protected void deserializeStateData(ProcedureStateSerializer serializer) throws IOException {
072    super.deserializeStateData(serializer);
073    serializer.deserialize(OpenRegionProcedureStateData.class);
074  }
075
076  @Override
077  protected ProcedureMetrics getProcedureMetrics(MasterProcedureEnv env) {
078    return env.getAssignmentManager().getAssignmentManagerMetrics().getOpenProcMetrics();
079  }
080
081  private void regionOpenedWithoutPersistingToMeta(AssignmentManager am, RegionStateNode regionNode,
082      TransitionCode transitionCode, long openSeqNum) throws IOException {
083    if (openSeqNum < regionNode.getOpenSeqNum()) {
084      LOG.warn(
085        "Received report {} transition from {} for {}, pid={} but the new openSeqNum {}" +
086          " is less than the current one {}, ignoring...",
087        transitionCode, targetServer, regionNode, getProcId(), openSeqNum,
088        regionNode.getOpenSeqNum());
089    } else {
090      regionNode.setOpenSeqNum(openSeqNum);
091    }
092    am.regionOpenedWithoutPersistingToMeta(regionNode);
093  }
094
095  @Override
096  protected void checkTransition(RegionStateNode regionNode, TransitionCode transitionCode,
097      long openSeqNum) throws UnexpectedStateException {
098    switch (transitionCode) {
099      case OPENED:
100        if (openSeqNum < 0) {
101          throw new UnexpectedStateException("Received report unexpected " + TransitionCode.OPENED +
102            " transition openSeqNum=" + openSeqNum + ", " + regionNode + ", proc=" + this);
103        }
104        break;
105      case FAILED_OPEN:
106        break;
107      default:
108        throw new UnexpectedStateException(
109          "Received report unexpected " + transitionCode + " transition, " +
110            regionNode.toShortString() + ", " + this + ", expected OPENED or FAILED_OPEN.");
111    }
112  }
113
114  @Override
115  protected void updateTransitionWithoutPersistingToMeta(MasterProcedureEnv env,
116      RegionStateNode regionNode, TransitionCode transitionCode, long openSeqNum)
117      throws IOException {
118    if (transitionCode == TransitionCode.OPENED) {
119      regionOpenedWithoutPersistingToMeta(env.getAssignmentManager(), regionNode, transitionCode,
120        openSeqNum);
121    } else {
122      assert transitionCode == TransitionCode.FAILED_OPEN;
123      // will not persist to meta if giveUp is false
124      env.getAssignmentManager().regionFailedOpen(regionNode, false);
125    }
126  }
127
128  @Override
129  protected void restoreSucceedState(AssignmentManager am, RegionStateNode regionNode,
130      long openSeqNum) throws IOException {
131    if (regionNode.getState() == State.OPEN) {
132      // should have already been persisted, ignore
133      return;
134    }
135    regionOpenedWithoutPersistingToMeta(am, regionNode, TransitionCode.OPENED, openSeqNum);
136  }
137}