001/**
002 *
003 * Licensed to the Apache Software Foundation (ASF) under one
004 * or more contributor license agreements.  See the NOTICE file
005 * distributed with this work for additional information
006 * regarding copyright ownership.  The ASF licenses this file
007 * to you under the Apache License, Version 2.0 (the
008 * "License"); you may not use this file except in compliance
009 * with the License.  You may obtain a copy of the License at
010 *
011 *     http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing, software
014 * distributed under the License is distributed on an "AS IS" BASIS,
015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016 * See the License for the specific language governing permissions and
017 * limitations under the License.
018 */
019package org.apache.hadoop.hbase.master.procedure;
020
021import java.io.IOException;
022import java.util.Optional;
023
024import org.apache.hadoop.fs.Path;
025import org.apache.hadoop.hbase.DoNotRetryIOException;
026import org.apache.hadoop.hbase.ServerName;
027import org.apache.hadoop.hbase.procedure2.ProcedureStateSerializer;
028import org.apache.hadoop.hbase.procedure2.RemoteProcedureDispatcher;
029import org.apache.hadoop.hbase.regionserver.SplitWALCallable;
030import org.apache.hadoop.hbase.wal.AbstractFSWALProvider;
031import org.apache.yetus.audience.InterfaceAudience;
032import org.slf4j.Logger;
033import org.slf4j.LoggerFactory;
034
035import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
036import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos;
037/**
038 * A remote procedure which is used to send split WAL request to region server.
039 * it will return null if the task is succeed or return a DoNotRetryIOException
040 * {@link SplitWALProcedure} will help handle the situation that encounter
041 * DoNotRetryIOException. Otherwise it will retry until succeed.
042 */
043@InterfaceAudience.Private
044public class SplitWALRemoteProcedure extends ServerRemoteProcedure
045    implements ServerProcedureInterface {
046  private static final Logger LOG = LoggerFactory.getLogger(SplitWALRemoteProcedure.class);
047  private String walPath;
048  private ServerName crashedServer;
049
050  public SplitWALRemoteProcedure() {
051  }
052
053  public SplitWALRemoteProcedure(ServerName worker, ServerName crashedServer, String wal) {
054    this.targetServer = worker;
055    this.crashedServer = crashedServer;
056    this.walPath = wal;
057  }
058
059  @Override
060  protected void rollback(MasterProcedureEnv env) throws IOException, InterruptedException {
061    throw new UnsupportedOperationException();
062  }
063
064  @Override
065  protected boolean abort(MasterProcedureEnv env) {
066    return false;
067  }
068
069  @Override
070  protected void serializeStateData(ProcedureStateSerializer serializer) throws IOException {
071    MasterProcedureProtos.SplitWALRemoteData.Builder builder =
072        MasterProcedureProtos.SplitWALRemoteData.newBuilder();
073    builder.setWalPath(walPath).setWorker(ProtobufUtil.toServerName(targetServer))
074        .setCrashedServer(ProtobufUtil.toServerName(crashedServer));
075    serializer.serialize(builder.build());
076  }
077
078  @Override
079  protected void deserializeStateData(ProcedureStateSerializer serializer) throws IOException {
080    MasterProcedureProtos.SplitWALRemoteData data =
081        serializer.deserialize(MasterProcedureProtos.SplitWALRemoteData.class);
082    walPath = data.getWalPath();
083    targetServer = ProtobufUtil.toServerName(data.getWorker());
084    crashedServer = ProtobufUtil.toServerName(data.getCrashedServer());
085  }
086
087  @Override
088  public Optional<RemoteProcedureDispatcher.RemoteOperation> remoteCallBuild(MasterProcedureEnv env,
089      ServerName serverName) {
090    return Optional
091        .of(new RSProcedureDispatcher.ServerOperation(this, getProcId(), SplitWALCallable.class,
092            MasterProcedureProtos.SplitWALParameter.newBuilder().setWalPath(walPath).build()
093                .toByteArray()));
094  }
095
096  @Override
097  protected void complete(MasterProcedureEnv env, Throwable error) {
098    if (error == null) {
099      LOG.info("split WAL {} on {} succeeded", walPath, targetServer);
100      try {
101        env.getMasterServices().getSplitWALManager().deleteSplitWAL(walPath);
102      } catch (IOException e) {
103        LOG.warn("remove WAL {} failed, ignore...", walPath, e);
104      }
105      succ = true;
106    } else {
107      if (error instanceof DoNotRetryIOException) {
108        LOG.warn("WAL split task of {} send to a wrong server {}, will retry on another server",
109          walPath, targetServer, error);
110        succ = true;
111      } else {
112        LOG.warn("split WAL {} failed, retry...", walPath, error);
113        succ = false;
114      }
115    }
116  }
117
118  public String getWAL() {
119    return this.walPath;
120  }
121
122  @Override
123  public ServerName getServerName() {
124    // return the crashed server is to use the queue of root ServerCrashProcedure
125    return this.crashedServer;
126  }
127
128  @Override
129  public boolean hasMetaTableRegion() {
130    return AbstractFSWALProvider.isMetaFile(new Path(walPath));
131  }
132
133  @Override
134  public ServerOperationType getServerOperationType() {
135    return ServerOperationType.SPLIT_WAL_REMOTE;
136  }
137}