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.procedure; 019 020import java.io.IOException; 021import org.apache.hadoop.hbase.ServerName; 022import org.apache.hadoop.hbase.procedure2.ProcedureStateSerializer; 023import org.apache.hadoop.hbase.procedure2.ProcedureSuspendedException; 024import org.apache.hadoop.hbase.procedure2.ProcedureUtil; 025import org.apache.hadoop.hbase.procedure2.ProcedureYieldException; 026import org.apache.hadoop.hbase.procedure2.StateMachineProcedure; 027import org.apache.hadoop.hbase.util.RetryCounter; 028import org.apache.yetus.audience.InterfaceAudience; 029import org.slf4j.Logger; 030import org.slf4j.LoggerFactory; 031 032import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos.SwitchRpcThrottleState; 033import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos.SwitchRpcThrottleStateData; 034import org.apache.hadoop.hbase.shaded.protobuf.generated.ProcedureProtos; 035 036/** 037 * The procedure to switch rpc throttle 038 */ 039@InterfaceAudience.Private 040public class SwitchRpcThrottleProcedure 041 extends StateMachineProcedure<MasterProcedureEnv, SwitchRpcThrottleState> 042 implements GlobalProcedureInterface { 043 044 private static Logger LOG = LoggerFactory.getLogger(SwitchRpcThrottleProcedure.class); 045 046 private boolean rpcThrottleEnabled; 047 private ProcedurePrepareLatch syncLatch; 048 private ServerName serverName; 049 private RetryCounter retryCounter; 050 051 public SwitchRpcThrottleProcedure() { 052 } 053 054 public SwitchRpcThrottleProcedure(boolean rpcThrottleEnabled, ServerName serverName, 055 final ProcedurePrepareLatch syncLatch) { 056 this.syncLatch = syncLatch; 057 this.rpcThrottleEnabled = rpcThrottleEnabled; 058 this.serverName = serverName; 059 } 060 061 @Override 062 protected Flow executeFromState(MasterProcedureEnv env, SwitchRpcThrottleState state) 063 throws ProcedureSuspendedException, ProcedureYieldException, InterruptedException { 064 switch (state) { 065 case UPDATE_SWITCH_RPC_THROTTLE_STORAGE: 066 try { 067 switchThrottleState(env, rpcThrottleEnabled); 068 } catch (IOException e) { 069 if (retryCounter == null) { 070 retryCounter = ProcedureUtil.createRetryCounter(env.getMasterConfiguration()); 071 } 072 long backoff = retryCounter.getBackoffTimeAndIncrementAttempts(); 073 LOG.warn("Failed to store rpc throttle value {}, sleep {} secs and retry", 074 rpcThrottleEnabled, backoff / 1000, e); 075 setTimeout(Math.toIntExact(backoff)); 076 setState(ProcedureProtos.ProcedureState.WAITING_TIMEOUT); 077 skipPersistence(); 078 throw new ProcedureSuspendedException(); 079 } 080 setNextState(SwitchRpcThrottleState.SWITCH_RPC_THROTTLE_ON_RS); 081 return Flow.HAS_MORE_STATE; 082 case SWITCH_RPC_THROTTLE_ON_RS: 083 SwitchRpcThrottleRemoteProcedure[] subProcedures = 084 env.getMasterServices().getServerManager().getOnlineServersList().stream() 085 .map(sn -> new SwitchRpcThrottleRemoteProcedure(sn, rpcThrottleEnabled)) 086 .toArray(SwitchRpcThrottleRemoteProcedure[]::new); 087 addChildProcedure(subProcedures); 088 setNextState(SwitchRpcThrottleState.POST_SWITCH_RPC_THROTTLE); 089 return Flow.HAS_MORE_STATE; 090 case POST_SWITCH_RPC_THROTTLE: 091 ProcedurePrepareLatch.releaseLatch(syncLatch, this); 092 return Flow.NO_MORE_STATE; 093 default: 094 throw new UnsupportedOperationException("unhandled state=" + state); 095 } 096 } 097 098 @Override 099 protected void rollbackState(MasterProcedureEnv env, SwitchRpcThrottleState state) 100 throws IOException, InterruptedException { 101 } 102 103 @Override 104 protected SwitchRpcThrottleState getState(int stateId) { 105 return SwitchRpcThrottleState.forNumber(stateId); 106 } 107 108 @Override 109 protected int getStateId(SwitchRpcThrottleState throttleState) { 110 return throttleState.getNumber(); 111 } 112 113 @Override 114 protected SwitchRpcThrottleState getInitialState() { 115 return SwitchRpcThrottleState.UPDATE_SWITCH_RPC_THROTTLE_STORAGE; 116 } 117 118 @Override 119 protected SwitchRpcThrottleState getCurrentState() { 120 return super.getCurrentState(); 121 } 122 123 @Override 124 protected void serializeStateData(ProcedureStateSerializer serializer) throws IOException { 125 super.serializeStateData(serializer); 126 serializer.serialize( 127 SwitchRpcThrottleStateData.newBuilder().setRpcThrottleEnabled(rpcThrottleEnabled).build()); 128 } 129 130 @Override 131 protected void deserializeStateData(ProcedureStateSerializer serializer) throws IOException { 132 super.deserializeStateData(serializer); 133 SwitchRpcThrottleStateData data = serializer.deserialize(SwitchRpcThrottleStateData.class); 134 rpcThrottleEnabled = data.getRpcThrottleEnabled(); 135 } 136 137 @Override 138 public String getGlobalId() { 139 return getClass().getSimpleName(); 140 } 141 142 private void switchThrottleState(MasterProcedureEnv env, boolean rpcThrottleEnabled) 143 throws IOException { 144 env.getMasterServices().getRpcThrottleStateStore().set(rpcThrottleEnabled); 145 } 146 147 @Override 148 public void toStringClassDetails(StringBuilder sb) { 149 sb.append(getClass().getSimpleName()); 150 sb.append(" server="); 151 sb.append(serverName); 152 sb.append(", rpcThrottleEnabled="); 153 sb.append(rpcThrottleEnabled); 154 } 155}