use of org.apache.hadoop.hdds.utils.Cache in project ozone by apache.
the class ContainerStateMachine method applyTransaction.
/*
* ApplyTransaction calls in Ratis are sequential.
*/
@Override
public CompletableFuture<Message> applyTransaction(TransactionContext trx) {
long index = trx.getLogEntry().getIndex();
try {
// Remove the stateMachine data once both followers have caught up. If any
// one of the follower is behind, the pending queue will max out as
// configurable limit on pending request size and count and then will
// block and client will backoff as a result of that.
removeStateMachineDataIfNeeded(index);
// as soon as its applied and such entry exists in the cache.
if (!waitOnBothFollowers) {
stateMachineDataCache.removeIf(k -> k >= index);
}
DispatcherContext.Builder builder = new DispatcherContext.Builder().setTerm(trx.getLogEntry().getTerm()).setLogIndex(index);
long applyTxnStartTime = Time.monotonicNowNanos();
applyTransactionSemaphore.acquire();
metrics.incNumApplyTransactionsOps();
ContainerCommandRequestProto requestProto = getContainerCommandRequestProto(gid, trx.getStateMachineLogEntry().getLogData());
Type cmdType = requestProto.getCmdType();
// Make sure that in write chunk, the user data is not set
if (cmdType == Type.WriteChunk) {
Preconditions.checkArgument(requestProto.getWriteChunk().getData().isEmpty());
builder.setStage(DispatcherContext.WriteChunkStage.COMMIT_DATA);
}
if (cmdType == Type.WriteChunk || cmdType == Type.PutSmallFile || cmdType == Type.PutBlock || cmdType == Type.CreateContainer) {
builder.setContainer2BCSIDMap(container2BCSIDMap);
}
CompletableFuture<Message> applyTransactionFuture = new CompletableFuture<>();
final Consumer<Exception> exceptionHandler = e -> {
LOG.error("gid {} : ApplyTransaction failed. cmd {} logIndex " + "{} exception {}", gid, requestProto.getCmdType(), index, e);
stateMachineHealthy.compareAndSet(true, false);
metrics.incNumApplyTransactionsFails();
applyTransactionFuture.completeExceptionally(e);
};
// Ensure the command gets executed in a separate thread than
// stateMachineUpdater thread which is calling applyTransaction here.
final CompletableFuture<ContainerCommandResponseProto> future = submitTask(requestProto, builder, exceptionHandler);
future.thenApply(r -> {
if (trx.getServerRole() == RaftPeerRole.LEADER && trx.getStateMachineContext() != null) {
long startTime = (long) trx.getStateMachineContext();
metrics.incPipelineLatency(cmdType, (Time.monotonicNowNanos() - startTime) / 1000000L);
}
// unhealthy
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 {} : ApplyTransaction failed. cmd {} logIndex {} msg : " + "{} Container Result: {}", gid, r.getCmdType(), index, r.getMessage(), r.getResult());
metrics.incNumApplyTransactionsFails();
// Since the applyTransaction now is completed exceptionally,
// before any further snapshot is taken , the exception will be
// caught in stateMachineUpdater in Ratis and ratis server will
// shutdown.
applyTransactionFuture.completeExceptionally(sce);
stateMachineHealthy.compareAndSet(true, false);
ratisServer.handleApplyTransactionFailure(gid, trx.getServerRole());
} else {
if (LOG.isDebugEnabled()) {
LOG.debug("gid {} : ApplyTransaction completed. cmd {} logIndex {} msg : " + "{} Container Result: {}", gid, r.getCmdType(), index, r.getMessage(), r.getResult());
}
if (cmdType == Type.WriteChunk || cmdType == Type.PutSmallFile) {
metrics.incNumBytesCommittedCount(requestProto.getWriteChunk().getChunkData().getLen());
}
applyTransactionFuture.complete(r::toByteString);
// failures before.
if (isStateMachineHealthy()) {
final Long previous = applyTransactionCompletionMap.put(index, trx.getLogEntry().getTerm());
Preconditions.checkState(previous == null);
updateLastApplied();
}
}
return applyTransactionFuture;
}).whenComplete((r, t) -> {
if (t != null) {
stateMachineHealthy.set(false);
LOG.error("gid {} : ApplyTransaction failed. cmd {} logIndex " + "{} exception {}", gid, requestProto.getCmdType(), index, t);
}
applyTransactionSemaphore.release();
metrics.recordApplyTransactionCompletion(Time.monotonicNowNanos() - applyTxnStartTime);
});
return applyTransactionFuture;
} catch (InterruptedException e) {
metrics.incNumApplyTransactionsFails();
Thread.currentThread().interrupt();
return completeExceptionally(e);
} catch (IOException e) {
metrics.incNumApplyTransactionsFails();
return completeExceptionally(e);
}
}
Aggregations