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