diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/DeletedBlockLogStateManagerImpl.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/DeletedBlockLogStateManagerImpl.java index 88a596a14577..7f45f5cb2d19 100644 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/DeletedBlockLogStateManagerImpl.java +++ b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/DeletedBlockLogStateManagerImpl.java @@ -240,7 +240,7 @@ public DeletedBlockLogStateManager build() throws IOException { final DeletedBlockLogStateManager impl = new DeletedBlockLogStateManagerImpl( deletedBlocksTransactionTable, statefulServiceConfigTable, containerManager, transactionBuffer); - return scmRatisServer.getProxyHandler(new DeletedBlockLogStateManagerInvoker(impl)); + return scmRatisServer.getProxyHandler(new DeletedBlockLogStateManagerInvoker(impl, scmRatisServer)); } } } diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ha/SCMHAInvocationHandler.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ha/SCMHAInvocationHandler.java index 382f18819205..aa35fbf6fbff 100644 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ha/SCMHAInvocationHandler.java +++ b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ha/SCMHAInvocationHandler.java @@ -44,15 +44,12 @@ public class SCMHAInvocationHandler implements InvocationHandler { private final RequestType requestType; private final Object localHandler; private final SCMRatisServer ratisHandler; - private final ScmInvoker invoker; public SCMHAInvocationHandler(final RequestType requestType, final Object localHandler, - final ScmInvoker invoker, final SCMRatisServer ratisHandler) { this.requestType = requestType; this.localHandler = localHandler; - this.invoker = invoker; this.ratisHandler = ratisHandler; if (ratisHandler != null) { ratisHandler.registerStateMachineHandler(requestType, localHandler); @@ -87,9 +84,6 @@ private Object invokeLocal(Method method, Object[] args) method, localHandler, args); } try { - if (invoker != null) { - return invoker.invokeLocal(method.getName(), args); - } return method.invoke(localHandler, args); } catch (Exception e) { throw translateException(e); @@ -104,6 +98,7 @@ private Object invokeRatis(Method method, Object[] args) if (LOG.isTraceEnabled()) { LOG.trace("Invoking method {} on target {}", method, ratisHandler); } + try { switch (method.getAnnotation(Replicate.class).invocationType()) { case CLIENT: @@ -143,7 +138,7 @@ private Object invokeRatisClient(Method method, Object[] args) throw response.getException(); } - private static SCMException translateException(Throwable t) { + public static SCMException translateException(Throwable t) { if (t instanceof SCMException) { return (SCMException) t; } diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ha/SCMRatisServer.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ha/SCMRatisServer.java index 689c3aff8ef9..169ee9e3fafa 100644 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ha/SCMRatisServer.java +++ b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ha/SCMRatisServer.java @@ -25,6 +25,7 @@ import org.apache.hadoop.hdds.protocol.proto.SCMRatisProtocol.RequestType; import org.apache.hadoop.hdds.scm.AddSCMRequest; import org.apache.hadoop.hdds.scm.RemoveSCMRequest; +import org.apache.hadoop.hdds.scm.ha.invoker.ScmInvoker; import org.apache.ratis.grpc.GrpcTlsConfig; import org.apache.ratis.protocol.RaftPeerId; import org.apache.ratis.protocol.exceptions.NotLeaderException; @@ -71,17 +72,14 @@ SCMRatisResponse submitRequest(SCMRatisRequest request) RaftPeerId getLeaderId(); - default T getProxyHandler(final RequestType type, final Class intf, final T impl) { - return getProxyHandler(type, intf, impl, null); - } - default T getProxyHandler(ScmInvoker invoker) { - return getProxyHandler(invoker.getType(), invoker.getApi(), invoker.getImpl(), invoker); + registerStateMachineHandler(invoker.getType(), invoker.getImpl()); + return invoker.getProxy(); } - default T getProxyHandler(RequestType type, Class intf, T impl, ScmInvoker invoker) { + default T getProxyHandler(RequestType type, Class intf, T impl) { final SCMHAInvocationHandler invocationHandler = - new SCMHAInvocationHandler(type, impl, invoker, this); + new SCMHAInvocationHandler(type, impl, this); return intf.cast(Proxy.newProxyInstance(getClass().getClassLoader(), new Class[] {intf}, invocationHandler)); } diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ha/ScmInvoker.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ha/ScmInvoker.java deleted file mode 100644 index 2bc1202fcd9f..000000000000 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ha/ScmInvoker.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hdds.scm.ha; - -import org.apache.hadoop.hdds.protocol.proto.SCMRatisProtocol.RequestType; - -/** - * Invokes methods without using reflection. - */ -public interface ScmInvoker { - RequestType getType(); - - Class getApi(); - - T getImpl(); - - Object invokeLocal(String methodName, Object[] args) throws Exception; -} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ha/invoker/DeletedBlockLogStateManagerInvoker.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ha/invoker/DeletedBlockLogStateManagerInvoker.java index 9574ac1c0d38..ba1317b079b8 100644 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ha/invoker/DeletedBlockLogStateManagerInvoker.java +++ b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ha/invoker/DeletedBlockLogStateManagerInvoker.java @@ -17,20 +17,50 @@ package org.apache.hadoop.hdds.scm.ha.invoker; +import com.google.protobuf.ByteString; +import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import org.apache.hadoop.hdds.protocol.proto.HddsProtos.DeletedBlocksTransactionSummary; import org.apache.hadoop.hdds.protocol.proto.SCMRatisProtocol.RequestType; +import org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.DeletedBlocksTransaction; import org.apache.hadoop.hdds.scm.block.DeletedBlockLogStateManager; -import org.apache.hadoop.hdds.scm.ha.ScmInvoker; +import org.apache.hadoop.hdds.scm.ha.SCMRatisServer; import org.apache.hadoop.hdds.utils.db.Table; /** * Invoker for DeletedBlockLogStateManager local (non-@Replicate) methods. */ -public class DeletedBlockLogStateManagerInvoker implements ScmInvoker { +public class DeletedBlockLogStateManagerInvoker extends ScmInvoker { private final DeletedBlockLogStateManager impl; - public DeletedBlockLogStateManagerInvoker(DeletedBlockLogStateManager impl) { + enum ReplicateMethod implements NameAndParameterTypes { + addTransactionsToDB(new Class[] {ArrayList.class, DeletedBlocksTransactionSummary.class}), + removeTransactionsFromDB(new Class[] {ArrayList.class, DeletedBlocksTransactionSummary.class}),; + + private final Class[][] parameterTypes; + + ReplicateMethod(Class[] parameterTypes) { + final Class[][] types = new Class[parameterTypes.length + 1][]; + for (int i = 0; i <= parameterTypes.length; ++i) { + types[i] = Arrays.copyOf(parameterTypes, i); + } + this.parameterTypes = types; + } + + @Override + public String getName() { + return name(); + } + + @Override + public Class[] getParameterTypes(int numArgs) { + return parameterTypes[numArgs]; + } + } + + public DeletedBlockLogStateManagerInvoker(DeletedBlockLogStateManager impl, SCMRatisServer scmRatisServer) { + super(scmRatisServer); this.impl = impl; } @@ -49,6 +79,56 @@ public DeletedBlockLogStateManager getImpl() { return impl; } + @Override + public DeletedBlockLogStateManager getProxy() { + return new DeletedBlockLogStateManager() { + @Override + public void addTransactionsToDB(ArrayList txs) + throws IOException { + final Object[] args = {txs}; + invokeRatisServer(ReplicateMethod.addTransactionsToDB, args); + } + + @Override + public void addTransactionsToDB(ArrayList txs, + DeletedBlocksTransactionSummary summary) throws IOException { + final Object[] args = {txs, summary}; + invokeRatisServer(ReplicateMethod.addTransactionsToDB, args); + } + + @Override + public void removeTransactionsFromDB(ArrayList txIDs) + throws IOException { + final Object[] args = {txIDs}; + invokeRatisServer(ReplicateMethod.removeTransactionsFromDB, args); + } + + @Override + public void removeTransactionsFromDB(ArrayList txIDs, + DeletedBlocksTransactionSummary summary) throws IOException { + final Object[] args = {txIDs, summary}; + invokeRatisServer(ReplicateMethod.removeTransactionsFromDB, args); + } + + @Override + public Table.KeyValueIterator getReadOnlyIterator() throws IOException { + return impl.getReadOnlyIterator(); + } + + @Override + public void onFlush() { + impl.onFlush(); + } + + @Override + public void reinitialize( + Table deletedBlocksTXTable, + Table statefulConfigTable) { + impl.reinitialize(deletedBlocksTXTable, statefulConfigTable); + } + }; + } + // Code generated for DeletedBlockLogStateManager. Do not modify. @SuppressWarnings("unchecked") @Override diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ha/invoker/ScmInvoker.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ha/invoker/ScmInvoker.java new file mode 100644 index 000000000000..322cf177ad61 --- /dev/null +++ b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ha/invoker/ScmInvoker.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hadoop.hdds.scm.ha.invoker; + +import static org.apache.hadoop.hdds.scm.ha.SCMHAInvocationHandler.translateException; + +import org.apache.hadoop.hdds.protocol.proto.SCMRatisProtocol.RequestType; +import org.apache.hadoop.hdds.scm.exceptions.SCMException; +import org.apache.hadoop.hdds.scm.ha.SCMRatisRequest; +import org.apache.hadoop.hdds.scm.ha.SCMRatisResponse; +import org.apache.hadoop.hdds.scm.ha.SCMRatisServer; + +/** + * Invokes methods without using reflection. + */ +public abstract class ScmInvoker { + private final SCMRatisServer ratisHandler; + + ScmInvoker(SCMRatisServer ratisHandler) { + this.ratisHandler = ratisHandler; + } + + public abstract RequestType getType(); + + public abstract Class getApi(); + + public abstract T getImpl(); + + public abstract T getProxy(); + + abstract Object invokeLocal(String methodName, Object[] args) throws Exception; + + Object invokeRatisServer(NameAndParameterTypes method, Object[] args) throws SCMException { + try { + final SCMRatisRequest request = SCMRatisRequest.of( + getType(), method.getName(), method.getParameterTypes(args.length), args); + final SCMRatisResponse response = ratisHandler.submitRequest(request); + if (response.isSuccess()) { + return response.getResult(); + } + throw response.getException(); + } catch (Exception e) { + throw translateException(e); + } + } + + interface NameAndParameterTypes { + String getName(); + + Class[] getParameterTypes(int numArgs); + } +}