You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ratis.apache.org by sh...@apache.org on 2018/11/05 10:05:59 UTC
incubator-ratis git commit: RATIS-362. Add a Builder for
TransactionContext. Contributed by Tsz Wo Nicholas Sze.
Repository: incubator-ratis
Updated Branches:
refs/heads/master 8055e5d6e -> 380baa9fd
RATIS-362. Add a Builder for TransactionContext. Contributed by Tsz Wo Nicholas Sze.
Project: http://git-wip-us.apache.org/repos/asf/incubator-ratis/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ratis/commit/380baa9f
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ratis/tree/380baa9f
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ratis/diff/380baa9f
Branch: refs/heads/master
Commit: 380baa9fd200af3fb09c038d21d8ab4c20fd4123
Parents: 8055e5d
Author: Shashikant Banerjee <sh...@apache.org>
Authored: Mon Nov 5 15:35:08 2018 +0530
Committer: Shashikant Banerjee <sh...@apache.org>
Committed: Mon Nov 5 15:35:08 2018 +0530
----------------------------------------------------------------------
.../org/apache/ratis/util/Preconditions.java | 11 +--
.../filestore/FileStoreStateMachine.java | 14 +--
.../ratis/server/impl/RaftServerImpl.java | 7 +-
.../apache/ratis/server/storage/RaftLog.java | 3 +-
.../ratis/statemachine/TransactionContext.java | 95 ++++++++++++++++++--
.../statemachine/impl/BaseStateMachine.java | 8 +-
.../impl/TransactionContextImpl.java | 28 +++---
.../SimpleStateMachine4Testing.java | 10 ++-
.../ratis/statemachine/TestStateMachine.java | 9 +-
9 files changed, 134 insertions(+), 51 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/380baa9f/ratis-common/src/main/java/org/apache/ratis/util/Preconditions.java
----------------------------------------------------------------------
diff --git a/ratis-common/src/main/java/org/apache/ratis/util/Preconditions.java b/ratis-common/src/main/java/org/apache/ratis/util/Preconditions.java
index 7af2201..6ebfdc7 100644
--- a/ratis-common/src/main/java/org/apache/ratis/util/Preconditions.java
+++ b/ratis-common/src/main/java/org/apache/ratis/util/Preconditions.java
@@ -73,11 +73,12 @@ public interface Preconditions {
}
}
+ static void assertNull(Object object, Supplier<String> message) {
+ assertTrue(object == null, message);
+ }
+
static void assertNull(Object object, String name) {
- if (object != null) {
- throw new IllegalStateException(
- name + " is expected to be null but "
- + name + " = " + object + " != null, class = " + object.getClass());
- }
+ assertNull(object, () -> name + " is expected to be null but "
+ + name + " = " + object + " != null, class = " + object.getClass());
}
}
http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/380baa9f/ratis-examples/src/main/java/org/apache/ratis/examples/filestore/FileStoreStateMachine.java
----------------------------------------------------------------------
diff --git a/ratis-examples/src/main/java/org/apache/ratis/examples/filestore/FileStoreStateMachine.java b/ratis-examples/src/main/java/org/apache/ratis/examples/filestore/FileStoreStateMachine.java
index 04bed04..73f6d93 100644
--- a/ratis-examples/src/main/java/org/apache/ratis/examples/filestore/FileStoreStateMachine.java
+++ b/ratis-examples/src/main/java/org/apache/ratis/examples/filestore/FileStoreStateMachine.java
@@ -31,13 +31,11 @@ import org.apache.ratis.protocol.Message;
import org.apache.ratis.protocol.RaftClientRequest;
import org.apache.ratis.protocol.RaftGroupId;
import org.apache.ratis.server.RaftServer;
-import org.apache.ratis.server.impl.ServerProtoUtils;
import org.apache.ratis.server.storage.RaftStorage;
import org.apache.ratis.statemachine.StateMachineStorage;
import org.apache.ratis.statemachine.TransactionContext;
import org.apache.ratis.statemachine.impl.BaseStateMachine;
import org.apache.ratis.statemachine.impl.SimpleStateMachineStorage;
-import org.apache.ratis.statemachine.impl.TransactionContextImpl;
import org.apache.ratis.thirdparty.com.google.protobuf.ByteString;
import org.apache.ratis.thirdparty.com.google.protobuf.InvalidProtocolBufferException;
import org.apache.ratis.util.FileUtils;
@@ -95,17 +93,19 @@ public class FileStoreStateMachine extends BaseStateMachine {
public TransactionContext startTransaction(RaftClientRequest request) throws IOException {
final ByteString content = request.getMessage().getContent();
final FileStoreRequestProto proto = FileStoreRequestProto.parseFrom(content);
- final StateMachineLogEntryProto log;
+ final TransactionContext.Builder b = TransactionContext.newBuilder()
+ .setStateMachine(this)
+ .setClientRequest(request);
+
if (proto.getRequestCase() == FileStoreRequestProto.RequestCase.WRITE) {
final WriteRequestProto write = proto.getWrite();
final FileStoreRequestProto newProto = FileStoreRequestProto.newBuilder()
.setWriteHeader(write.getHeader()).build();
- log = ServerProtoUtils.toStateMachineLogEntryProto(request, newProto.toByteString(), write.getData());
+ b.setLogData(newProto.toByteString()).setStateMachineData(write.getData());
} else {
- log = ServerProtoUtils.toStateMachineLogEntryProto(request, content, null);
+ b.setLogData(content);
}
-
- return new TransactionContextImpl(this, request, log);
+ return b.build();
}
@Override
http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/380baa9f/ratis-server/src/main/java/org/apache/ratis/server/impl/RaftServerImpl.java
----------------------------------------------------------------------
diff --git a/ratis-server/src/main/java/org/apache/ratis/server/impl/RaftServerImpl.java b/ratis-server/src/main/java/org/apache/ratis/server/impl/RaftServerImpl.java
index ed7b8bc..09e4550 100644
--- a/ratis-server/src/main/java/org/apache/ratis/server/impl/RaftServerImpl.java
+++ b/ratis-server/src/main/java/org/apache/ratis/server/impl/RaftServerImpl.java
@@ -32,7 +32,6 @@ import org.apache.ratis.server.storage.RaftStorageDirectory;
import org.apache.ratis.statemachine.SnapshotInfo;
import org.apache.ratis.statemachine.StateMachine;
import org.apache.ratis.statemachine.TransactionContext;
-import org.apache.ratis.statemachine.impl.TransactionContextImpl;
import org.apache.ratis.thirdparty.com.google.common.annotations.VisibleForTesting;
import org.apache.ratis.util.*;
import org.slf4j.Logger;
@@ -1102,7 +1101,11 @@ public class RaftServerImpl implements RaftServerProtocol, RaftServerAsynchronou
// check whether there is a TransactionContext because we are the leader.
TransactionContext trx = role.getLeaderState()
.map(leader -> leader.getTransactionContext(next.getIndex())).orElseGet(
- () -> new TransactionContextImpl(role.getCurrentRole(), stateMachine, next));
+ () -> TransactionContext.newBuilder()
+ .setServerRole(role.getCurrentRole())
+ .setStateMachine(stateMachine)
+ .setLogEntry(next)
+ .build());
// Let the StateMachine inject logic for committed transactions in sequential order.
trx = stateMachine.applyTransactionSerial(trx);
http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/380baa9f/ratis-server/src/main/java/org/apache/ratis/server/storage/RaftLog.java
----------------------------------------------------------------------
diff --git a/ratis-server/src/main/java/org/apache/ratis/server/storage/RaftLog.java b/ratis-server/src/main/java/org/apache/ratis/server/storage/RaftLog.java
index 8b88b31..00650ca 100644
--- a/ratis-server/src/main/java/org/apache/ratis/server/storage/RaftLog.java
+++ b/ratis-server/src/main/java/org/apache/ratis/server/storage/RaftLog.java
@@ -151,7 +151,7 @@ public abstract class RaftLog implements Closeable {
}
// build the log entry after calling the StateMachine
- final LogEntryProto e = ServerProtoUtils.toLogEntryProto(operation.getStateMachineLogEntry(), term, nextIndex);
+ final LogEntryProto e = operation.initLogEntry(term, nextIndex);
int entrySize = e.getSerializedSize();
if (entrySize > maxBufferSize) {
@@ -160,7 +160,6 @@ public abstract class RaftLog implements Closeable {
+ maxBufferSize));
}
appendEntry(e);
- operation.setLogEntry(e);
return nextIndex;
}
}
http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/380baa9f/ratis-server/src/main/java/org/apache/ratis/statemachine/TransactionContext.java
----------------------------------------------------------------------
diff --git a/ratis-server/src/main/java/org/apache/ratis/statemachine/TransactionContext.java b/ratis-server/src/main/java/org/apache/ratis/statemachine/TransactionContext.java
index 0a53c9d..fa1cd61 100644
--- a/ratis-server/src/main/java/org/apache/ratis/statemachine/TransactionContext.java
+++ b/ratis-server/src/main/java/org/apache/ratis/statemachine/TransactionContext.java
@@ -18,13 +18,17 @@
package org.apache.ratis.statemachine;
import org.apache.ratis.proto.RaftProtos.LogEntryProto;
-import org.apache.ratis.proto.RaftProtos.LogEntryProto.LogEntryBodyCase;
import org.apache.ratis.proto.RaftProtos.RaftPeerRole;
import org.apache.ratis.proto.RaftProtos.StateMachineLogEntryProto;
import org.apache.ratis.protocol.RaftClientRequest;
+import org.apache.ratis.server.impl.ServerProtoUtils;
+import org.apache.ratis.statemachine.impl.TransactionContextImpl;
+import org.apache.ratis.thirdparty.com.google.protobuf.ByteString;
+import org.apache.ratis.util.Preconditions;
import java.io.IOException;
import java.util.Collection;
+import java.util.Objects;
/**
* Context for a transaction.
@@ -60,6 +64,9 @@ public interface TransactionContext {
*/
StateMachineLogEntryProto getStateMachineLogEntry();
+ /** Set exception in case of failure. */
+ TransactionContext setException(Exception exception);
+
/**
* Returns the exception from the {@link StateMachine} or the log
* @return the exception from the {@link StateMachine} or the log
@@ -81,13 +88,12 @@ public interface TransactionContext {
Object getStateMachineContext();
/**
- * Set the {@link LogEntryProto} the current {@link TransactionContext} specific to. The log
- * entry's body case must be {@link LogEntryBodyCase#STATEMACHINELOGENTRY}. The current
- * {@link TransactionContext} log entry must be null, otherwise, a exception will be thrown
- * @param logEntry target {@link LogEntryProto}
- * @return the current {@link TransactionContext} itself
+ * Initialize {@link LogEntryProto} using the internal {@link StateMachineLogEntryProto}.
+ * @param term The current term.
+ * @param index The index of the log entry.
+ * @return the result {@link LogEntryProto}
*/
- TransactionContext setLogEntry(LogEntryProto logEntry);
+ LogEntryProto initLogEntry(long term, long index);
/**
* Sets the data from the {@link StateMachine}
@@ -132,4 +138,79 @@ public interface TransactionContext {
* @return cancelled transaction
*/
TransactionContext cancelTransaction() throws IOException;
+
+ static Builder newBuilder() {
+ return new Builder();
+ }
+
+ class Builder {
+ private RaftPeerRole serverRole = RaftPeerRole.LEADER;
+ private StateMachine stateMachine;
+ private Object stateMachineContext;
+
+ private RaftClientRequest clientRequest;
+ private LogEntryProto logEntry;
+ private StateMachineLogEntryProto stateMachineLogEntry;
+ private ByteString logData;
+ private ByteString stateMachineData;
+
+ public Builder setServerRole(RaftPeerRole serverRole) {
+ this.serverRole = serverRole;
+ return this;
+ }
+
+ public Builder setStateMachine(StateMachine stateMachine) {
+ this.stateMachine = stateMachine;
+ return this;
+ }
+
+ public Builder setStateMachineContext(Object stateMachineContext) {
+ this.stateMachineContext = stateMachineContext;
+ return this;
+ }
+
+ public Builder setClientRequest(RaftClientRequest clientRequest) {
+ this.clientRequest = clientRequest;
+ return this;
+ }
+
+ public Builder setLogEntry(LogEntryProto logEntry) {
+ this.logEntry = logEntry;
+ return this;
+ }
+
+ public Builder setStateMachineLogEntry(StateMachineLogEntryProto stateMachineLogEntry) {
+ this.stateMachineLogEntry = stateMachineLogEntry;
+ return this;
+ }
+
+ public Builder setLogData(ByteString logData) {
+ this.logData = logData;
+ return this;
+ }
+
+ public Builder setStateMachineData(ByteString stateMachineData) {
+ this.stateMachineData = stateMachineData;
+ return this;
+ }
+
+ public TransactionContext build() {
+ Objects.requireNonNull(serverRole, "serverRole == null");
+ Objects.requireNonNull(stateMachine, "stateMachine == null");
+ if (clientRequest != null) {
+ Preconditions.assertTrue(serverRole == RaftPeerRole.LEADER,
+ () -> "serverRole MUST be LEADER since clientRequest != null, serverRole is " + serverRole);
+ Preconditions.assertNull(logEntry, () -> "logEntry MUST be null since clientRequest != null");
+ if (stateMachineLogEntry == null) {
+ stateMachineLogEntry = ServerProtoUtils.toStateMachineLogEntryProto(clientRequest, logData, stateMachineData);
+ }
+ return new TransactionContextImpl(stateMachine, clientRequest, stateMachineLogEntry, stateMachineContext);
+ } else {
+ Objects.requireNonNull(logEntry, "logEntry MUST NOT be null since clientRequest == null");
+ Preconditions.assertTrue(logEntry.hasStateMachineLogEntry(),
+ () -> "Unexpected logEntry: stateMachineLogEntry not found, logEntry=" + logEntry);
+ return new TransactionContextImpl(serverRole, stateMachine, logEntry);
+ }
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/380baa9f/ratis-server/src/main/java/org/apache/ratis/statemachine/impl/BaseStateMachine.java
----------------------------------------------------------------------
diff --git a/ratis-server/src/main/java/org/apache/ratis/statemachine/impl/BaseStateMachine.java b/ratis-server/src/main/java/org/apache/ratis/statemachine/impl/BaseStateMachine.java
index 119432e..8a09bd4 100644
--- a/ratis-server/src/main/java/org/apache/ratis/statemachine/impl/BaseStateMachine.java
+++ b/ratis-server/src/main/java/org/apache/ratis/statemachine/impl/BaseStateMachine.java
@@ -170,9 +170,11 @@ public class BaseStateMachine implements StateMachine {
}
@Override
- public TransactionContext startTransaction(RaftClientRequest request)
- throws IOException {
- return new TransactionContextImpl(this, request, null);
+ public TransactionContext startTransaction(RaftClientRequest request) throws IOException {
+ return TransactionContext.newBuilder()
+ .setStateMachine(this)
+ .setClientRequest(request)
+ .build();
}
@Override
http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/380baa9f/ratis-server/src/main/java/org/apache/ratis/statemachine/impl/TransactionContextImpl.java
----------------------------------------------------------------------
diff --git a/ratis-server/src/main/java/org/apache/ratis/statemachine/impl/TransactionContextImpl.java b/ratis-server/src/main/java/org/apache/ratis/statemachine/impl/TransactionContextImpl.java
index 5e4936a..3a2fb12 100644
--- a/ratis-server/src/main/java/org/apache/ratis/statemachine/impl/TransactionContextImpl.java
+++ b/ratis-server/src/main/java/org/apache/ratis/statemachine/impl/TransactionContextImpl.java
@@ -18,7 +18,6 @@
package org.apache.ratis.statemachine.impl;
import org.apache.ratis.proto.RaftProtos.LogEntryProto;
-import org.apache.ratis.proto.RaftProtos.LogEntryProto.LogEntryBodyCase;
import org.apache.ratis.proto.RaftProtos.RaftPeerRole;
import org.apache.ratis.proto.RaftProtos.StateMachineLogEntryProto;
import org.apache.ratis.protocol.RaftClientRequest;
@@ -32,6 +31,8 @@ import java.util.Objects;
/**
* Implementation of {@link TransactionContext}
+ *
+ * This is a private API. Applications should use {@link TransactionContext} and {@link TransactionContext.Builder}.
*/
public class TransactionContextImpl implements TransactionContext {
/** The role of the server when this object is created. */
@@ -71,13 +72,6 @@ public class TransactionContextImpl implements TransactionContext {
this.stateMachine = stateMachine;
}
- /** The same as this(stateMachine, clientRequest, smLogEntryProto, null). */
- public TransactionContextImpl(
- StateMachine stateMachine, RaftClientRequest clientRequest,
- StateMachineLogEntryProto smLogEntryProto) {
- this(stateMachine, clientRequest, smLogEntryProto, null);
- }
-
/**
* Construct a {@link TransactionContext} from a client request.
* Used by the state machine to start a transaction
@@ -101,7 +95,7 @@ public class TransactionContextImpl implements TransactionContext {
*/
public TransactionContextImpl(RaftPeerRole serverRole, StateMachine stateMachine, LogEntryProto logEntry) {
this(serverRole, stateMachine);
- setLogEntry(logEntry);
+ this.logEntry = logEntry;
this.smLogEntryProto = logEntry.getStateMachineLogEntry();
}
@@ -137,14 +131,11 @@ public class TransactionContextImpl implements TransactionContext {
}
@Override
- public TransactionContext setLogEntry(LogEntryProto logEntry) {
- Objects.requireNonNull(logEntry, "logEntry == null");
- Preconditions.assertTrue(logEntry.getLogEntryBodyCase() == LogEntryBodyCase.STATEMACHINELOGENTRY,
- () -> "LogEntryBodyCase = " + logEntry.getLogEntryBodyCase()
- + " != " + LogEntryBodyCase.STATEMACHINELOGENTRY + ", logEntry=" + logEntry);
- Preconditions.assertTrue(this.logEntry == null, "this.logEntry != null");
- this.logEntry = logEntry;
- return this;
+ public LogEntryProto initLogEntry(long term, long index) {
+ Preconditions.assertTrue(serverRole == RaftPeerRole.LEADER);
+ Preconditions.assertNull(logEntry, "logEntry");
+ Objects.requireNonNull(smLogEntryProto, "smLogEntryProto == null");
+ return logEntry = ServerProtoUtils.toLogEntryProto(smLogEntryProto, term, index);
}
@Override
@@ -158,7 +149,8 @@ public class TransactionContextImpl implements TransactionContext {
return logEntry;
}
- private TransactionContext setException(IOException ioe) {
+ @Override
+ public TransactionContext setException(Exception ioe) {
assert exception != null;
this.exception = ioe;
return this;
http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/380baa9f/ratis-server/src/test/java/org/apache/ratis/statemachine/SimpleStateMachine4Testing.java
----------------------------------------------------------------------
diff --git a/ratis-server/src/test/java/org/apache/ratis/statemachine/SimpleStateMachine4Testing.java b/ratis-server/src/test/java/org/apache/ratis/statemachine/SimpleStateMachine4Testing.java
index 84be87b..d5fdf53 100644
--- a/ratis-server/src/test/java/org/apache/ratis/statemachine/SimpleStateMachine4Testing.java
+++ b/ratis-server/src/test/java/org/apache/ratis/statemachine/SimpleStateMachine4Testing.java
@@ -39,7 +39,6 @@ import org.apache.ratis.server.storage.RaftStorage;
import org.apache.ratis.statemachine.impl.BaseStateMachine;
import org.apache.ratis.statemachine.impl.SimpleStateMachineStorage;
import org.apache.ratis.statemachine.impl.SingleFileSnapshotInfo;
-import org.apache.ratis.statemachine.impl.TransactionContextImpl;
import org.apache.ratis.thirdparty.com.google.protobuf.ByteString;
import org.apache.ratis.util.Daemon;
import org.apache.ratis.util.JavaUtils;
@@ -303,10 +302,13 @@ public class SimpleStateMachine4Testing extends BaseStateMachine {
static final ByteString STATE_MACHINE_DATA = ByteString.copyFromUtf8("StateMachine Data");
@Override
- public TransactionContext startTransaction(RaftClientRequest request) throws IOException {
+ public TransactionContext startTransaction(RaftClientRequest request) {
blocking.await(Blocking.Type.START_TRANSACTION);
- return new TransactionContextImpl(this, request,
- ServerProtoUtils.toStateMachineLogEntryProto(request, null, STATE_MACHINE_DATA));
+ return TransactionContext.newBuilder()
+ .setStateMachine(this)
+ .setClientRequest(request)
+ .setStateMachineData(STATE_MACHINE_DATA)
+ .build();
}
@Override
http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/380baa9f/ratis-server/src/test/java/org/apache/ratis/statemachine/TestStateMachine.java
----------------------------------------------------------------------
diff --git a/ratis-server/src/test/java/org/apache/ratis/statemachine/TestStateMachine.java b/ratis-server/src/test/java/org/apache/ratis/statemachine/TestStateMachine.java
index 329b02b..a4dc88a 100644
--- a/ratis-server/src/test/java/org/apache/ratis/statemachine/TestStateMachine.java
+++ b/ratis-server/src/test/java/org/apache/ratis/statemachine/TestStateMachine.java
@@ -34,7 +34,6 @@ import org.apache.ratis.server.impl.RaftServerImpl;
import org.apache.ratis.server.impl.RaftServerProxy;
import org.apache.ratis.server.impl.RaftServerTestUtil;
import org.apache.ratis.server.simulation.MiniRaftClusterWithSimulatedRpc;
-import org.apache.ratis.statemachine.impl.TransactionContextImpl;
import org.apache.ratis.util.LogUtils;
import org.junit.*;
@@ -75,11 +74,15 @@ public class TestStateMachine extends BaseTest implements MiniRaftClusterWithSim
ConcurrentLinkedQueue<Long> applied = new ConcurrentLinkedQueue<>();
@Override
- public TransactionContext startTransaction(RaftClientRequest request) throws IOException {
+ public TransactionContext startTransaction(RaftClientRequest request) {
// only leader will get this call
isLeader.set(true);
// send the next transaction id as the "context" from SM
- return new TransactionContextImpl(this, request, null, transactions.incrementAndGet());
+ return TransactionContext.newBuilder()
+ .setStateMachine(this)
+ .setClientRequest(request)
+ .setStateMachineContext(transactions.incrementAndGet())
+ .build();
}
@Override