HDDS-1208. ContainerStateMachine should set chunk data as state machine data for ratis. Contributed by Lokesh Jain.

This commit is contained in:
Lokesh Jain 2019-03-06 17:00:37 +05:30
parent c79f139519
commit 129fd5dd18

View File

@ -78,7 +78,6 @@
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -277,7 +276,7 @@ public long takeSnapshot() throws IOException {
public TransactionContext startTransaction(RaftClientRequest request) public TransactionContext startTransaction(RaftClientRequest request)
throws IOException { throws IOException {
final ContainerCommandRequestProto proto = final ContainerCommandRequestProto proto =
getRequestProto(request.getMessage().getContent()); getContainerCommandRequestProto(request.getMessage().getContent());
Preconditions.checkArgument(request.getRaftGroupId().equals(gid)); Preconditions.checkArgument(request.getRaftGroupId().equals(gid));
try (Scope scope = TracingUtil try (Scope scope = TracingUtil
.importAndCreateScope(proto.getCmdType().name(), proto.getTraceID())) { .importAndCreateScope(proto.getCmdType().name(), proto.getTraceID())) {
@ -294,17 +293,6 @@ public TransactionContext startTransaction(RaftClientRequest request)
} }
if (proto.getCmdType() == Type.WriteChunk) { if (proto.getCmdType() == Type.WriteChunk) {
final WriteChunkRequestProto write = proto.getWriteChunk(); final WriteChunkRequestProto write = proto.getWriteChunk();
// create the state machine data proto
final WriteChunkRequestProto dataWriteChunkProto =
WriteChunkRequestProto
.newBuilder(write)
.build();
ContainerCommandRequestProto dataContainerCommandProto =
ContainerCommandRequestProto
.newBuilder(proto)
.setWriteChunk(dataWriteChunkProto)
.build();
// create the log entry proto // create the log entry proto
final WriteChunkRequestProto commitWriteChunkProto = final WriteChunkRequestProto commitWriteChunkProto =
WriteChunkRequestProto.newBuilder() WriteChunkRequestProto.newBuilder()
@ -323,7 +311,7 @@ public TransactionContext startTransaction(RaftClientRequest request)
.setClientRequest(request) .setClientRequest(request)
.setStateMachine(this) .setStateMachine(this)
.setServerRole(RaftPeerRole.LEADER) .setServerRole(RaftPeerRole.LEADER)
.setStateMachineData(dataContainerCommandProto.toByteString()) .setStateMachineData(write.getData())
.setLogData(commitContainerCommandProto.toByteString()) .setLogData(commitContainerCommandProto.toByteString())
.build(); .build();
} else { } else {
@ -341,8 +329,8 @@ private ByteString getStateMachineData(StateMachineLogEntryProto entryProto) {
return entryProto.getStateMachineEntry().getStateMachineData(); return entryProto.getStateMachineEntry().getStateMachineData();
} }
private ContainerCommandRequestProto getRequestProto(ByteString request) private ContainerCommandRequestProto getContainerCommandRequestProto(
throws InvalidProtocolBufferException { ByteString request) throws InvalidProtocolBufferException {
// TODO: We can avoid creating new builder and set pipeline Id if // TODO: We can avoid creating new builder and set pipeline Id if
// the client is already sending the pipeline id, then we just have to // the client is already sending the pipeline id, then we just have to
// validate the pipeline Id. // validate the pipeline Id.
@ -353,7 +341,9 @@ private ContainerCommandRequestProto getRequestProto(ByteString request)
private ContainerCommandResponseProto dispatchCommand( private ContainerCommandResponseProto dispatchCommand(
ContainerCommandRequestProto requestProto, DispatcherContext context) { ContainerCommandRequestProto requestProto, DispatcherContext context) {
LOG.trace("dispatch {}", requestProto); LOG.trace("dispatch {} containerID={} pipelineID={} traceID={}",
requestProto.getCmdType(), requestProto.getContainerID(),
requestProto.getPipelineID(), requestProto.getTraceID());
if (isBlockTokenEnabled) { if (isBlockTokenEnabled) {
try { try {
// ServerInterceptors intercepts incoming request and creates ugi. // ServerInterceptors intercepts incoming request and creates ugi.
@ -432,8 +422,15 @@ private CompletableFuture<Message> handleWriteChunk(
public CompletableFuture<Message> writeStateMachineData(LogEntryProto entry) { public CompletableFuture<Message> writeStateMachineData(LogEntryProto entry) {
try { try {
metrics.incNumWriteStateMachineOps(); metrics.incNumWriteStateMachineOps();
final ContainerCommandRequestProto requestProto = ContainerCommandRequestProto requestProto =
getRequestProto(getStateMachineData(entry.getStateMachineLogEntry())); getContainerCommandRequestProto(
entry.getStateMachineLogEntry().getLogData());
WriteChunkRequestProto writeChunk =
WriteChunkRequestProto.newBuilder(requestProto.getWriteChunk())
.setData(getStateMachineData(entry.getStateMachineLogEntry()))
.build();
requestProto = ContainerCommandRequestProto.newBuilder(requestProto)
.setWriteChunk(writeChunk).build();
Type cmdType = requestProto.getCmdType(); Type cmdType = requestProto.getCmdType();
// For only writeChunk, there will be writeStateMachineData call. // For only writeChunk, there will be writeStateMachineData call.
@ -457,7 +454,7 @@ public CompletableFuture<Message> query(Message request) {
try { try {
metrics.incNumReadStateMachineOps(); metrics.incNumReadStateMachineOps();
final ContainerCommandRequestProto requestProto = final ContainerCommandRequestProto requestProto =
getRequestProto(request.getContent()); getContainerCommandRequestProto(request.getContent());
return CompletableFuture.completedFuture(runCommand(requestProto, null)); return CompletableFuture.completedFuture(runCommand(requestProto, null));
} catch (IOException e) { } catch (IOException e) {
metrics.incNumReadStateMachineFails(); metrics.incNumReadStateMachineFails();
@ -507,34 +504,8 @@ private ByteString readStateMachineData(
*/ */
private ByteString getCachedStateMachineData(Long logIndex, long term, private ByteString getCachedStateMachineData(Long logIndex, long term,
ContainerCommandRequestProto requestProto) throws ExecutionException { ContainerCommandRequestProto requestProto) throws ExecutionException {
try { return stateMachineDataCache.get(logIndex,
return reconstructWriteChunkRequest( () -> readStateMachineData(requestProto, term, logIndex));
stateMachineDataCache.get(logIndex, new Callable<ByteString>() {
@Override
public ByteString call() throws Exception {
return readStateMachineData(requestProto, term, logIndex);
}
}), requestProto);
} catch (ExecutionException e) {
throw e;
}
}
private ByteString reconstructWriteChunkRequest(ByteString data,
ContainerCommandRequestProto requestProto) {
WriteChunkRequestProto writeChunkRequestProto =
requestProto.getWriteChunk();
// reconstruct the write chunk request
final WriteChunkRequestProto.Builder dataWriteChunkProto =
WriteChunkRequestProto.newBuilder(writeChunkRequestProto)
// adding the state machine data
.setData(data);
ContainerCommandRequestProto.Builder newStateMachineProto =
ContainerCommandRequestProto.newBuilder(requestProto)
.setWriteChunk(dataWriteChunkProto);
return newStateMachineProto.build().toByteString();
} }
/** /**
@ -568,7 +539,8 @@ public CompletableFuture<ByteString> readStateMachineData(
} }
try { try {
final ContainerCommandRequestProto requestProto = final ContainerCommandRequestProto requestProto =
getRequestProto(entry.getStateMachineLogEntry().getLogData()); getContainerCommandRequestProto(
entry.getStateMachineLogEntry().getLogData());
// readStateMachineData should only be called for "write" to Ratis. // readStateMachineData should only be called for "write" to Ratis.
Preconditions.checkArgument(!HddsUtils.isReadOnly(requestProto)); Preconditions.checkArgument(!HddsUtils.isReadOnly(requestProto));
if (requestProto.getCmdType() == Type.WriteChunk) { if (requestProto.getCmdType() == Type.WriteChunk) {
@ -632,7 +604,8 @@ public CompletableFuture<Message> applyTransaction(TransactionContext trx) {
try { try {
metrics.incNumApplyTransactionsOps(); metrics.incNumApplyTransactionsOps();
ContainerCommandRequestProto requestProto = ContainerCommandRequestProto requestProto =
getRequestProto(trx.getStateMachineLogEntry().getLogData()); getContainerCommandRequestProto(
trx.getStateMachineLogEntry().getLogData());
Type cmdType = requestProto.getCmdType(); Type cmdType = requestProto.getCmdType();
// Make sure that in write chunk, the user data is not set // Make sure that in write chunk, the user data is not set
if (cmdType == Type.WriteChunk) { if (cmdType == Type.WriteChunk) {