use of bftsmart.consensus.app.PreComputeBatchExecutable in project bftsmart by blockchain-jd-com.
the class ServiceReplica method receiveMessages.
public void receiveMessages(int[] consId, int[] regencies, int[] leaders, CertifiedDecision[] cDecs, TOMMessage[][] requests, List<byte[]> asyncResponseLinkedList, boolean isRollback) {
int numRequests = 0;
int consensusCount = 0;
List<TOMMessage> toBatch = new ArrayList<>();
List<MessageContext> msgCtxts = new ArrayList<>();
boolean noop = true;
for (TOMMessage[] requestsFromConsensus : requests) {
TOMMessage firstRequest = requestsFromConsensus[0];
int requestCount = 0;
noop = true;
for (TOMMessage request : requestsFromConsensus) {
LOGGER.info("(ServiceReplica.receiveMessages) request view id = {}, curr view id = {}, request type = {}", request.getViewID(), serverViewController.getCurrentViewId(), request.getReqType());
// 暂时没有节点间的视图ID同步过程,在处理RECONFIG这类更新视图的操作时先不考虑视图ID落后的情况
if (request.getViewID() <= serverViewController.getCurrentViewId()) {
if (request.getReqType() == TOMMessageType.ORDERED_REQUEST || request.getReqType() == TOMMessageType.RECONFIG) {
noop = false;
numRequests++;
MessageContext msgCtx = new MessageContext(request.getSender(), request.getViewID(), request.getReqType(), request.getSession(), request.getSequence(), request.getOperationId(), request.getReplyServer(), request.serializedMessageSignature, firstRequest.timestamp, request.numOfNonces, request.seed, regencies[consensusCount], leaders[consensusCount], consId[consensusCount], cDecs[consensusCount].getConsMessages(), firstRequest, false);
if (requestCount + 1 == requestsFromConsensus.length) {
msgCtx.setLastInBatch();
}
request.deliveryTime = System.nanoTime();
if (executor instanceof PreComputeBatchExecutable) {
LOGGER.debug("(ServiceReplica.receiveMessages) Batching request from {}", request.getSender());
// This is used to deliver the content decided by a consensus instance directly
// to
// a Recoverable object. It is useful to allow the application to create a log
// and
// store the proof associated with decisions (which are needed by replicas
// that are asking for a state transfer).
// if (this.recoverer != null)
// this.recoverer.Op(msgCtx.getConsensusId(), request.getContent(), msgCtx);
// deliver requests and contexts to the executor later
msgCtxts.add(msgCtx);
toBatch.add(request);
if (request.getReqType() == TOMMessageType.RECONFIG) {
serverViewController.enqueueUpdate(request);
}
} else if (executor instanceof FIFOExecutable) {
LOGGER.debug("(ServiceReplica.receiveMessages) Delivering request from {} via FifoExecutable", request.getSender());
// that are asking for a state transfer).
if (this.recoverer != null)
this.recoverer.Op(msgCtx.getConsensusId(), request.getContent(), msgCtx);
// This is used to deliver the requests to the application and obtain a reply to
// deliver
// to the clients. The raw decision is passed to the application in the line
// above.
byte[] response = ((FIFOExecutable) executor).executeOrderedFIFO(request.getContent(), msgCtx, request.getSender(), request.getOperationId());
// Generate the messages to send back to the clients
request.reply = new TOMMessage(id, request.getSession(), request.getSequence(), request.getOperationId(), response, null, serverViewController.getCurrentViewId(), request.getReqType());
LOGGER.debug("(ServiceReplica.receiveMessages) sending reply to {}", request.getSender());
replier.manageReply(request, msgCtx);
} else if (executor instanceof SingleExecutable) {
LOGGER.debug("(ServiceReplica.receiveMessages) Delivering request from {} via SingleExecutable", request.getSender());
// that are asking for a state transfer).
if (this.recoverer != null)
this.recoverer.Op(msgCtx.getConsensusId(), request.getContent(), msgCtx);
// This is used to deliver the requests to the application and obtain a reply to
// deliver
// to the clients. The raw decision is passed to the application in the line
// above.
byte[] response = ((SingleExecutable) executor).executeOrdered(request.getContent(), msgCtx);
// Generate the messages to send back to the clients
request.reply = new TOMMessage(id, request.getSession(), request.getSequence(), request.getOperationId(), response, null, serverViewController.getCurrentViewId(), request.getReqType());
LOGGER.debug("(ServiceReplica.receiveMessages) sending reply to {}", request.getSender());
replier.manageReply(request, msgCtx);
} else {
throw new UnsupportedOperationException("Non-existent interface");
}
} else // else if (request.getReqType() == TOMMessageType.RECONFIG) {
// noop = false;
// numRequests++;
// serverViewController.enqueueUpdate(request);
// }
{
throw new RuntimeException("Should never reach here!");
}
}
// else if (request.getViewID() < serverViewController.getCurrentViewId()) { // message sender had an old
// // view,
// // resend the message to
// // him (but only if it came from
// // consensus an not state transfer)
// View view = serverViewController.getCurrentView();
//
// List<NodeNetwork> addressesTemp = new ArrayList<>();
//
// for (int i = 0; i < view.getProcesses().length; i++) {
// int cpuId = view.getProcesses()[i];
// NodeNetwork inetSocketAddress = view.getAddress(cpuId);
//
// if (inetSocketAddress.getHost().equals("0.0.0.0")) {
// // proc docker env
// String host = serverViewController.getStaticConf().getOuterHostConfig().getHost(cpuId);
//
// NodeNetwork tempSocketAddress = new NodeNetwork(host, inetSocketAddress.getConsensusPort(),
// -1);
// LOGGER.info("I am proc {}, tempSocketAddress.getAddress().getHostAddress() = {}",
// serverViewController.getStaticConf().getProcessId(), host);
// addressesTemp.add(tempSocketAddress);
// } else {
// LOGGER.info("I am proc {}, tempSocketAddress.getAddress().getHostAddress() = {}",
// serverViewController.getStaticConf().getProcessId(), inetSocketAddress.toUrl());
// addressesTemp.add(new NodeNetwork(inetSocketAddress.getHost(),
// inetSocketAddress.getConsensusPort(), -1));
// }
// }
//
// View replyView = new View(view.getId(), view.getProcesses(), view.getF(),
// addressesTemp.toArray(new NodeNetwork[addressesTemp.size()]));
// LOGGER.info("I am proc {}, view = {}, hashCode = {}, reply View = {}",
// this.serverViewController.getStaticConf().getProcessId(), view, view.hashCode(), replyView);
//
// getTomLayer().getCommunication().send(new int[] { request.getSender() },
// new TOMMessage(serverViewController.getStaticConf().getProcessId(), request.getSession(),
// request.getSequence(), request.getOperationId(), TOMUtil.getBytes(replyView),
// serverViewController.getCurrentViewId(), request.getReqType()));
// }
requestCount++;
}
// hence the invocation of "noop"
if (noop && this.recoverer != null) {
LOGGER.debug("(ServiceReplica.receiveMessages) I am proc {}, host = {}, port = {}. Delivering a no-op to the recoverer", this.serverViewController.getStaticConf().getProcessId(), this.serverViewController.getStaticConf().getRemoteAddress(this.serverViewController.getStaticConf().getProcessId()).getHost(), this.serverViewController.getStaticConf().getRemoteAddress(this.serverViewController.getStaticConf().getProcessId()).getConsensusPort());
LOGGER.debug("I am proc {} , host = {}, port = {}.--- A consensus instance finished, but there were no commands to deliver to the application.", this.serverViewController.getStaticConf().getProcessId(), this.serverViewController.getStaticConf().getRemoteAddress(this.serverViewController.getStaticConf().getProcessId()).getHost(), this.serverViewController.getStaticConf().getRemoteAddress(this.serverViewController.getStaticConf().getProcessId()).getConsensusPort());
LOGGER.debug("I am proc {} , host = {}, port = {}.--- Notifying recoverable about a blank consensus.", this.serverViewController.getStaticConf().getProcessId(), this.serverViewController.getStaticConf().getRemoteAddress(this.serverViewController.getStaticConf().getProcessId()).getHost(), this.serverViewController.getStaticConf().getRemoteAddress(this.serverViewController.getStaticConf().getProcessId()).getConsensusPort());
byte[][] batch = null;
MessageContext[] msgCtx = null;
if (requestsFromConsensus.length > 0) {
// Make new batch to deliver
batch = new byte[requestsFromConsensus.length][];
msgCtx = new MessageContext[requestsFromConsensus.length];
// Put messages in the batch
int line = 0;
for (TOMMessage m : requestsFromConsensus) {
batch[line] = m.getContent();
msgCtx[line] = new MessageContext(m.getSender(), m.getViewID(), m.getReqType(), m.getSession(), m.getSequence(), m.getOperationId(), m.getReplyServer(), m.serializedMessageSignature, firstRequest.timestamp, m.numOfNonces, m.seed, regencies[consensusCount], leaders[consensusCount], consId[consensusCount], cDecs[consensusCount].getConsMessages(), firstRequest, true);
msgCtx[line].setLastInBatch();
line++;
}
}
this.recoverer.noOp(consId[consensusCount], batch, msgCtx);
// MessageContext msgCtx = new MessageContext(-1, -1, null, -1, -1, -1, -1,
// null, // Since it is a noop, there is no need to pass info about the
// client...
// -1, 0, 0, regencies[consensusCount], leaders[consensusCount],
// consId[consensusCount], cDecs[consensusCount].getConsMessages(), //... but
// there is still need to pass info about the consensus
// null, true); // there is no command that is the first of the batch, since it
// is a noop
// msgCtx.setLastInBatch();
// this.recoverer.noOp(msgCtx.getConsensusId(), msgCtx);
}
consensusCount++;
}
if (executor instanceof PreComputeBatchExecutable && numRequests > 0) {
// Make new batch to deliver
byte[][] batch = new byte[numRequests][];
// ReplyContext replyContext = new ReplyContext().buildId(id)
// .buildCurrentViewId(serverViewController.getCurrentViewId())
// .buildNumRepliers(serverViewController.getStaticConf().getNumRepliers()).buildRepMan(repMan)
// .buildReplier(replier);
// List<ReplyContextMessage> replyContextMessages = new ArrayList<>();
// Put messages in the batch
int line = 0;
for (TOMMessage m : toBatch) {
if (m.getReqType() == TOMMessageType.RECONFIG) {
// 对于reconfig类型的消息,扩展消息才是交易本身
batch[line] = ((ReconfigureRequest) TOMUtil.getObject(m.getContent())).getExtendInfo();
} else {
batch[line] = m.getContent();
}
line++;
}
MessageContext[] msgContexts = new MessageContext[msgCtxts.size()];
msgContexts = msgCtxts.toArray(msgContexts);
// Deliver the batch and wait for replies
if (isRollback == false) {
byte[][] replies = ((PreComputeBatchExecutable) executor).executeBatch(batch, msgContexts);
}
if (toBatch.size() != asyncResponseLinkedList.size()) {
LOGGER.debug("(ServiceReplica.receiveMessages) toBatch.size() != asyncResponseLinkedList.size()");
return;
}
// Send the replies back to the client
for (int index = 0; index < toBatch.size(); index++) {
TOMMessage request = toBatch.get(index);
if (request.getReqType() == TOMMessageType.RECONFIG) {
continue;
}
// if request with backward viewid, reply msg will include view content
if (request.getViewID() < serverViewController.getCurrentViewId()) {
View view = serverViewController.getCurrentView();
List<NodeNetwork> addressesTemp = new ArrayList<>();
for (int i = 0; i < view.getProcesses().length; i++) {
int cpuId = view.getProcesses()[i];
NodeNetwork inetSocketAddress = view.getAddress(cpuId);
if (inetSocketAddress.getHost().equals("0.0.0.0")) {
// proc docker env
String host = serverViewController.getStaticConf().getOuterHostConfig().getHost(cpuId);
NodeNetwork tempSocketAddress = new NodeNetwork(host, inetSocketAddress.getConsensusPort(), -1, inetSocketAddress.isConsensusSecure(), false);
LOGGER.info("I am proc {}, tempSocketAddress.getAddress().getHostAddress() = {}", serverViewController.getStaticConf().getProcessId(), host);
addressesTemp.add(tempSocketAddress);
} else {
LOGGER.info("I am proc {}, tempSocketAddress.getAddress().getHostAddress() = {}", serverViewController.getStaticConf().getProcessId(), inetSocketAddress.toString());
addressesTemp.add(new NodeNetwork(inetSocketAddress.getHost(), inetSocketAddress.getConsensusPort(), -1, inetSocketAddress.isConsensusSecure(), false));
}
}
View replyView = new View(view.getId(), view.getProcesses(), view.getF(), addressesTemp.toArray(new NodeNetwork[addressesTemp.size()]));
LOGGER.info("I am proc {}, view = {}, reply View = {}", this.serverViewController.getStaticConf().getProcessId(), view, replyView);
request.reply = new TOMMessage(id, request.getSession(), request.getSequence(), request.getOperationId(), asyncResponseLinkedList.get(index), TOMUtil.getBytes(replyView), serverViewController.getCurrentViewId(), request.getReqType());
} else {
request.reply = new TOMMessage(id, request.getSession(), request.getSequence(), request.getOperationId(), asyncResponseLinkedList.get(index), null, serverViewController.getCurrentViewId(), request.getReqType());
}
if (serverViewController.getStaticConf().getNumRepliers() > 0) {
LOGGER.debug("(ServiceReplica.receiveMessages) sending reply to {} with sequence number {} and operation ID {} via ReplyManager", request.getSender(), request.getSequence(), request.getOperationId());
repMan.send(request);
} else {
LOGGER.debug("(ServiceReplica.receiveMessages) sending reply to {} with sequence number {} and operation ID {}", request.getSender(), request.getSequence(), request.getOperationId());
replier.manageReply(request, msgContexts[index]);
// cs.send(new int[]{request.getSender()}, request.reply);
}
}
// DEBUG
LOGGER.debug("BATCHEXECUTOR END");
}
// End of: if (executor instanceof PreComputeBatchExecutable && numRequests > 0)
}
Aggregations