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 java.util.Optional; 022import org.apache.hadoop.fs.Path; 023import org.apache.hadoop.hbase.DoNotRetryIOException; 024import org.apache.hadoop.hbase.ServerName; 025import org.apache.hadoop.hbase.procedure2.ProcedureStateSerializer; 026import org.apache.hadoop.hbase.procedure2.RemoteProcedureDispatcher; 027import org.apache.hadoop.hbase.regionserver.SplitWALCallable; 028import org.apache.hadoop.hbase.wal.AbstractFSWALProvider; 029import org.apache.yetus.audience.InterfaceAudience; 030import org.slf4j.Logger; 031import org.slf4j.LoggerFactory; 032 033import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil; 034import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos; 035 036/** 037 * A remote procedure which is used to send split WAL request to region server. It will return null 038 * if the task succeeded or return a DoNotRetryIOException. {@link SplitWALProcedure} will help 039 * handle the situation that encounters DoNotRetryIOException. Otherwise it will retry until 040 * success. 041 */ 042@InterfaceAudience.Private 043public class SplitWALRemoteProcedure extends ServerRemoteProcedure 044 implements ServerProcedureInterface { 045 private static final Logger LOG = LoggerFactory.getLogger(SplitWALRemoteProcedure.class); 046 private String walPath; 047 private ServerName crashedServer; 048 049 public SplitWALRemoteProcedure() { 050 } 051 052 public SplitWALRemoteProcedure(ServerName worker, ServerName crashedServer, String wal) { 053 this.targetServer = worker; 054 this.crashedServer = crashedServer; 055 this.walPath = wal; 056 } 057 058 @Override 059 protected void rollback(MasterProcedureEnv env) throws IOException, InterruptedException { 060 throw new UnsupportedOperationException(); 061 } 062 063 @Override 064 protected boolean abort(MasterProcedureEnv env) { 065 return false; 066 } 067 068 @Override 069 protected void serializeStateData(ProcedureStateSerializer serializer) throws IOException { 070 MasterProcedureProtos.SplitWALRemoteData.Builder builder = 071 MasterProcedureProtos.SplitWALRemoteData.newBuilder(); 072 builder.setWalPath(walPath).setWorker(ProtobufUtil.toServerName(targetServer)) 073 .setCrashedServer(ProtobufUtil.toServerName(crashedServer)); 074 serializer.serialize(builder.build()); 075 } 076 077 @Override 078 protected void deserializeStateData(ProcedureStateSerializer serializer) throws IOException { 079 MasterProcedureProtos.SplitWALRemoteData data = 080 serializer.deserialize(MasterProcedureProtos.SplitWALRemoteData.class); 081 walPath = data.getWalPath(); 082 targetServer = ProtobufUtil.toServerName(data.getWorker()); 083 crashedServer = ProtobufUtil.toServerName(data.getCrashedServer()); 084 } 085 086 @Override 087 public Optional<RemoteProcedureDispatcher.RemoteOperation> remoteCallBuild(MasterProcedureEnv env, 088 ServerName serverName) { 089 return Optional.of(new RSProcedureDispatcher.ServerOperation(this, getProcId(), 090 SplitWALCallable.class, MasterProcedureProtos.SplitWALParameter.newBuilder() 091 .setWalPath(walPath).build().toByteArray())); 092 } 093 094 @Override 095 protected void complete(MasterProcedureEnv env, Throwable error) { 096 if (error == null) { 097 try { 098 env.getMasterServices().getSplitWALManager().archive(walPath); 099 } catch (IOException e) { 100 LOG.warn("Failed split of {}; ignore...", walPath, e); 101 } 102 succ = true; 103 } else { 104 if (error instanceof DoNotRetryIOException) { 105 LOG.warn("Sent {} to wrong server {}, try another", walPath, targetServer, error); 106 succ = true; 107 } else { 108 LOG.warn("Failed split of {}, retry...", walPath, error); 109 succ = false; 110 } 111 } 112 } 113 114 public String getWAL() { 115 return this.walPath; 116 } 117 118 @Override 119 public ServerName getServerName() { 120 // return the crashed server is to use the queue of root ServerCrashProcedure 121 return this.crashedServer; 122 } 123 124 @Override 125 public boolean hasMetaTableRegion() { 126 return AbstractFSWALProvider.isMetaFile(new Path(walPath)); 127 } 128 129 @Override 130 public ServerOperationType getServerOperationType() { 131 return ServerOperationType.SPLIT_WAL_REMOTE; 132 } 133 134 @Override 135 protected void toStringClassDetails(StringBuilder builder) { 136 builder.append(getProcName()); 137 if (this.targetServer != null) { 138 builder.append(", worker="); 139 builder.append(this.targetServer); 140 } 141 } 142 143 @Override 144 public String getProcName() { 145 return getClass().getSimpleName() + " " + SplitWALProcedure.getWALNameFromStrPath(getWAL()); 146 } 147}