Search in sources :

Example 1 with PreComputeBatchExecutable

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)
}
Also used : TOMMessage(bftsmart.tom.core.messages.TOMMessage) SingleExecutable(bftsmart.tom.server.SingleExecutable) ArrayList(java.util.ArrayList) FIFOExecutable(bftsmart.tom.server.FIFOExecutable) PreComputeBatchExecutable(bftsmart.consensus.app.PreComputeBatchExecutable) View(bftsmart.reconfiguration.views.View) NodeNetwork(bftsmart.reconfiguration.views.NodeNetwork)

Aggregations

PreComputeBatchExecutable (bftsmart.consensus.app.PreComputeBatchExecutable)1 NodeNetwork (bftsmart.reconfiguration.views.NodeNetwork)1 View (bftsmart.reconfiguration.views.View)1 TOMMessage (bftsmart.tom.core.messages.TOMMessage)1 FIFOExecutable (bftsmart.tom.server.FIFOExecutable)1 SingleExecutable (bftsmart.tom.server.SingleExecutable)1 ArrayList (java.util.ArrayList)1