use of org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.WriteChunkRequestProto in project ozone by apache.
the class ContainerStateMachine method handleWriteChunk.
private CompletableFuture<Message> handleWriteChunk(ContainerCommandRequestProto requestProto, long entryIndex, long term, long startTime) {
final WriteChunkRequestProto write = requestProto.getWriteChunk();
RaftServer server = ratisServer.getServer();
Preconditions.checkArgument(!write.getData().isEmpty());
try {
if (server.getDivision(gid).getInfo().isLeader()) {
stateMachineDataCache.put(entryIndex, write.getData());
}
} catch (InterruptedException ioe) {
Thread.currentThread().interrupt();
return completeExceptionally(ioe);
} catch (IOException ioe) {
return completeExceptionally(ioe);
}
DispatcherContext context = new DispatcherContext.Builder().setTerm(term).setLogIndex(entryIndex).setStage(DispatcherContext.WriteChunkStage.WRITE_DATA).setContainer2BCSIDMap(container2BCSIDMap).build();
CompletableFuture<Message> raftFuture = new CompletableFuture<>();
// ensure the write chunk happens asynchronously in writeChunkExecutor pool
// thread.
CompletableFuture<ContainerCommandResponseProto> writeChunkFuture = CompletableFuture.supplyAsync(() -> {
try {
return runCommand(requestProto, context);
} catch (Exception e) {
LOG.error("{}: writeChunk writeStateMachineData failed: blockId" + "{} logIndex {} chunkName {}", gid, write.getBlockID(), entryIndex, write.getChunkData().getChunkName(), e);
metrics.incNumWriteDataFails();
// write chunks go in parallel. It's possible that one write chunk
// see the stateMachine is marked unhealthy by other parallel thread
stateMachineHealthy.set(false);
raftFuture.completeExceptionally(e);
throw e;
}
}, getChunkExecutor(requestProto.getWriteChunk()));
writeChunkFutureMap.put(entryIndex, writeChunkFuture);
if (LOG.isDebugEnabled()) {
LOG.debug("{}: writeChunk writeStateMachineData : blockId" + "{} logIndex {} chunkName {}", gid, write.getBlockID(), entryIndex, write.getChunkData().getChunkName());
}
// Remove the future once it finishes execution from the
// writeChunkFutureMap.
writeChunkFuture.thenApply(r -> {
if (r.getResult() != ContainerProtos.Result.SUCCESS && r.getResult() != ContainerProtos.Result.CONTAINER_NOT_OPEN && r.getResult() != ContainerProtos.Result.CLOSED_CONTAINER_IO) {
StorageContainerException sce = new StorageContainerException(r.getMessage(), r.getResult());
LOG.error(gid + ": writeChunk writeStateMachineData failed: blockId" + write.getBlockID() + " logIndex " + entryIndex + " chunkName " + write.getChunkData().getChunkName() + " Error message: " + r.getMessage() + " Container Result: " + r.getResult());
metrics.incNumWriteDataFails();
// If the write fails currently we mark the stateMachine as unhealthy.
// This leads to pipeline close. Any change in that behavior requires
// handling the entry for the write chunk in cache.
stateMachineHealthy.set(false);
raftFuture.completeExceptionally(sce);
} else {
metrics.incNumBytesWrittenCount(requestProto.getWriteChunk().getChunkData().getLen());
if (LOG.isDebugEnabled()) {
LOG.debug(gid + ": writeChunk writeStateMachineData completed: blockId" + write.getBlockID() + " logIndex " + entryIndex + " chunkName " + write.getChunkData().getChunkName());
}
raftFuture.complete(r::toByteString);
metrics.recordWriteStateMachineCompletion(Time.monotonicNowNanos() - startTime);
}
writeChunkFutureMap.remove(entryIndex);
return r;
});
return raftFuture;
}
use of org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.WriteChunkRequestProto in project ozone by apache.
the class ContainerStateMachine method startTransaction.
@Override
public TransactionContext startTransaction(RaftClientRequest request) throws IOException {
long startTime = Time.monotonicNowNanos();
final ContainerCommandRequestProto proto = message2ContainerCommandRequestProto(request.getMessage());
Preconditions.checkArgument(request.getRaftGroupId().equals(gid));
try {
dispatcher.validateContainerCommand(proto);
} catch (IOException ioe) {
if (ioe instanceof ContainerNotOpenException) {
metrics.incNumContainerNotOpenVerifyFailures();
} else {
metrics.incNumStartTransactionVerifyFailures();
LOG.error("startTransaction validation failed on leader", ioe);
}
TransactionContext ctxt = TransactionContext.newBuilder().setClientRequest(request).setStateMachine(this).setServerRole(RaftPeerRole.LEADER).build();
ctxt.setException(ioe);
return ctxt;
}
if (proto.getCmdType() == Type.WriteChunk) {
final WriteChunkRequestProto write = proto.getWriteChunk();
// create the log entry proto
final WriteChunkRequestProto commitWriteChunkProto = WriteChunkRequestProto.newBuilder().setBlockID(write.getBlockID()).setChunkData(write.getChunkData()).build();
ContainerCommandRequestProto commitContainerCommandProto = ContainerCommandRequestProto.newBuilder(proto).setWriteChunk(commitWriteChunkProto).setTraceID(proto.getTraceID()).build();
Preconditions.checkArgument(write.hasData());
Preconditions.checkArgument(!write.getData().isEmpty());
return TransactionContext.newBuilder().setClientRequest(request).setStateMachine(this).setServerRole(RaftPeerRole.LEADER).setStateMachineContext(startTime).setStateMachineData(write.getData()).setLogData(commitContainerCommandProto.toByteString()).build();
} else {
return TransactionContext.newBuilder().setClientRequest(request).setStateMachine(this).setServerRole(RaftPeerRole.LEADER).setStateMachineContext(startTime).setLogData(proto.toByteString()).build();
}
}
use of org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.WriteChunkRequestProto in project ozone by apache.
the class TestHddsDispatcher method getReadChunkRequest.
/**
* Creates container read chunk request using input container write chunk
* request.
*
* @param writeChunkRequest - Input container write chunk request
* @return container read chunk request
*/
private ContainerCommandRequestProto getReadChunkRequest(ContainerCommandRequestProto writeChunkRequest) {
WriteChunkRequestProto writeChunk = writeChunkRequest.getWriteChunk();
ContainerProtos.ReadChunkRequestProto.Builder readChunkRequest = ContainerProtos.ReadChunkRequestProto.newBuilder().setBlockID(writeChunk.getBlockID()).setChunkData(writeChunk.getChunkData()).setReadChunkVersion(ContainerProtos.ReadChunkVersion.V1);
return ContainerCommandRequestProto.newBuilder().setCmdType(ContainerProtos.Type.ReadChunk).setContainerID(writeChunk.getBlockID().getContainerID()).setTraceID(writeChunkRequest.getTraceID()).setDatanodeUuid(writeChunkRequest.getDatanodeUuid()).setReadChunk(readChunkRequest).build();
}
use of org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.WriteChunkRequestProto in project ozone by apache.
the class ContainerStateMachine method write.
/*
* writeStateMachineData calls are not synchronized with each other
* and also with applyTransaction.
*/
@Override
public CompletableFuture<Message> write(LogEntryProto entry) {
try {
metrics.incNumWriteStateMachineOps();
long writeStateMachineStartTime = Time.monotonicNowNanos();
ContainerCommandRequestProto requestProto = getContainerCommandRequestProto(gid, 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();
// CreateContainer will happen as a part of writeChunk only.
switch(cmdType) {
case WriteChunk:
return handleWriteChunk(requestProto, entry.getIndex(), entry.getTerm(), writeStateMachineStartTime);
default:
throw new IllegalStateException("Cmd Type:" + cmdType + " should not have state machine data");
}
} catch (IOException e) {
metrics.incNumWriteStateMachineFails();
return completeExceptionally(e);
}
}
use of org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.WriteChunkRequestProto in project ozone by apache.
the class ContainerStateMachine method readStateMachineData.
private ByteString readStateMachineData(ContainerCommandRequestProto requestProto, long term, long index) throws IOException {
// the stateMachine data is not present in the stateMachine cache,
// increment the stateMachine cache miss count
metrics.incNumReadStateMachineMissCount();
WriteChunkRequestProto writeChunkRequestProto = requestProto.getWriteChunk();
ContainerProtos.ChunkInfo chunkInfo = writeChunkRequestProto.getChunkData();
// prepare the chunk to be read
ReadChunkRequestProto.Builder readChunkRequestProto = ReadChunkRequestProto.newBuilder().setBlockID(writeChunkRequestProto.getBlockID()).setChunkData(chunkInfo).setReadChunkVersion(ContainerProtos.ReadChunkVersion.V1);
ContainerCommandRequestProto dataContainerCommandProto = ContainerCommandRequestProto.newBuilder(requestProto).setCmdType(Type.ReadChunk).setReadChunk(readChunkRequestProto).build();
DispatcherContext context = new DispatcherContext.Builder().setTerm(term).setLogIndex(index).setReadFromTmpFile(true).build();
// read the chunk
ContainerCommandResponseProto response = dispatchCommand(dataContainerCommandProto, context);
if (response.getResult() != ContainerProtos.Result.SUCCESS) {
StorageContainerException sce = new StorageContainerException(response.getMessage(), response.getResult());
LOG.error("gid {} : ReadStateMachine failed. cmd {} logIndex {} msg : " + "{} Container Result: {}", gid, response.getCmdType(), index, response.getMessage(), response.getResult());
stateMachineHealthy.set(false);
throw sce;
}
ReadChunkResponseProto responseProto = response.getReadChunk();
ByteString data;
if (responseProto.hasData()) {
data = responseProto.getData();
} else {
data = BufferUtils.concatByteStrings(responseProto.getDataBuffers().getBuffersList());
}
// assert that the response has data in it.
Preconditions.checkNotNull(data, "read chunk data is null for chunk: %s", chunkInfo);
Preconditions.checkState(data.size() == chunkInfo.getLen(), "read chunk len=%s does not match chunk expected len=%s for chunk:%s", data.size(), chunkInfo.getLen(), chunkInfo);
return data;
}
Aggregations