Search in sources :

Example 21 with View

use of bftsmart.reconfiguration.views.View in project aware by bergerch.

the class DurableStateManager method SMReplyDeliver.

@Override
public void SMReplyDeliver(SMMessage msg, boolean isBFT) {
    lockTimer.lock();
    CSTSMMessage reply = (CSTSMMessage) msg;
    if (SVController.getStaticConf().isStateTransferEnabled()) {
        logger.debug("The state transfer protocol is enabled");
        logger.info("I received a state reply for CID " + reply.getCID() + " from replica " + reply.getSender());
        logger.info("Received CID: " + reply.getCID() + ". Waiting " + waitingCID);
        if (waitingCID != -1 && reply.getCID() == waitingCID) {
            int currentRegency = -1;
            int currentLeader = -1;
            View currentView = null;
            if (!appStateOnly) {
                senderRegencies.put(reply.getSender(), reply.getRegency());
                senderLeaders.put(reply.getSender(), reply.getLeader());
                senderViews.put(reply.getSender(), reply.getView());
                // senderProofs.put(msg.getSender(), msg.getState().getCertifiedDecision(SVController));
                if (enoughRegencies(reply.getRegency())) {
                    currentRegency = reply.getRegency();
                }
                if (enoughLeaders(reply.getLeader())) {
                    currentLeader = reply.getLeader();
                }
                if (enoughViews(reply.getView())) {
                    currentView = reply.getView();
                    if (!currentView.isMember(SVController.getStaticConf().getProcessId())) {
                        logger.warn("Not a member!");
                    }
                }
            // if (enoughProofs(waitingCID, this.tomLayer.getSynchronizer().getLCManager())) currentProof = msg.getState().getCertifiedDecision(SVController);
            } else {
                currentLeader = tomLayer.execManager.getCurrentLeader();
                currentRegency = tomLayer.getSynchronizer().getLCManager().getLastReg();
                currentView = SVController.getCurrentView();
            }
            logger.debug("The reply is for the CID that I want!");
            InetSocketAddress address = reply.getCstConfig().getAddress();
            Socket clientSocket;
            ApplicationState stateReceived = null;
            try {
                clientSocket = new Socket(address.getHostName(), address.getPort());
                ObjectInputStream in = new ObjectInputStream(clientSocket.getInputStream());
                stateReceived = (ApplicationState) in.readObject();
            } catch (UnknownHostException e) {
                // TODO Auto-generated catch block
                logger.error("Failed to connect to address", e);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                logger.error("Failed to connect to address", e);
            } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                logger.error("Failed to deserialize application state object", e);
            }
            if (stateReceived instanceof CSTState) {
                senderStates.put(reply.getSender(), stateReceived);
                if (reply.getSender() == cstRequest.getCheckpointReplica()) {
                    this.stateCkp = (CSTState) stateReceived;
                }
                if (reply.getSender() == cstRequest.getLogLower()) {
                    this.stateLower = (CSTState) stateReceived;
                }
                if (reply.getSender() == cstRequest.getLogUpper()) {
                    this.stateUpper = (CSTState) stateReceived;
                }
            }
            if (senderStates.size() == 3) {
                CommandsInfo[] lowerLog = stateLower.getLogLower();
                CommandsInfo[] upperLog = stateUpper.getLogUpper();
                logger.info("lowerLog ");
                if (lowerLog != null) {
                    logger.info("\t" + lowerLog.length);
                }
                logger.info("upperLog ");
                if (upperLog != null) {
                    logger.info("\t" + upperLog.length);
                }
                boolean haveState = false;
                byte[] lowerbytes = TOMUtil.getBytes(lowerLog);
                logger.debug("Log lower bytes size: " + lowerbytes.length);
                byte[] upperbytes = TOMUtil.getBytes(upperLog);
                logger.debug("Log upper bytes size: " + upperbytes.length);
                byte[] lowerLogHash = TOMUtil.computeHash(lowerbytes);
                byte[] upperLogHash = TOMUtil.computeHash(upperbytes);
                // validate lower log
                if (Arrays.equals(stateCkp.getHashLogLower(), lowerLogHash)) {
                    haveState = true;
                } else {
                    logger.error("Lower log does not match");
                }
                // validate upper log
                if (!haveState || !Arrays.equals(stateCkp.getHashLogUpper(), upperLogHash)) {
                    haveState = false;
                    logger.error("Upper log does not match");
                }
                CSTState statePlusLower = new CSTState(stateCkp.getSerializedState(), TOMUtil.getBytes(stateCkp.getSerializedState()), stateLower.getLogLower(), stateCkp.getHashLogLower(), null, null, stateCkp.getCheckpointCID(), stateUpper.getCheckpointCID(), SVController.getStaticConf().getProcessId());
                if (haveState) {
                    // validate checkpoint
                    logger.info("validating checkpoint!!!");
                    dt.getRecoverer().setState(statePlusLower);
                    byte[] currentStateHash = ((DurabilityCoordinator) dt.getRecoverer()).getCurrentStateHash();
                    if (!Arrays.equals(currentStateHash, stateUpper.getHashCheckpoint())) {
                        logger.error("ckp hash don't match");
                        haveState = false;
                    }
                }
                logger.info("Current regency: " + currentRegency);
                logger.info("Current leader: " + currentLeader);
                logger.info("Current view: " + currentView);
                if (currentRegency > -1 && currentLeader > -1 && currentView != null && haveState && (!isBFT || /*currentProof != null ||*/
                appStateOnly)) {
                    logger.info("---- RECEIVED VALID STATE ----");
                    logger.debug("The state of those replies is good!");
                    logger.debug("CID State requested: " + reply.getCID());
                    logger.debug("CID State received: " + stateUpper.getLastCID());
                    tomLayer.getSynchronizer().getLCManager().setLastReg(currentRegency);
                    tomLayer.getSynchronizer().getLCManager().setNextReg(currentRegency);
                    tomLayer.getSynchronizer().getLCManager().setNewLeader(currentLeader);
                    tomLayer.execManager.setNewLeader(currentLeader);
                    // stop my re-transmission of STOP messages for all regencies up to the current one
                    if (currentRegency > 0) {
                        tomLayer.getSynchronizer().removeSTOPretransmissions(currentRegency - 1);
                    }
                    logger.debug("trying to acquire deliverlock");
                    dt.deliverLock();
                    logger.debug("acquired");
                    // this makes the isRetrievingState() evaluates to false
                    waitingCID = -1;
                    dt.update(stateUpper);
                    // synchronization phase
                    if (!appStateOnly && execManager.stopped()) {
                        Queue<ConsensusMessage> stoppedMsgs = execManager.getStoppedMsgs();
                        for (ConsensusMessage stopped : stoppedMsgs) {
                            if (stopped.getNumber() > state.getLastCID()) {
                                execManager.addOutOfContextMessage(stopped);
                            }
                        }
                        execManager.clearStopped();
                        execManager.restart();
                    }
                    logger.info("Processing out of context messages");
                    tomLayer.processOutOfContext();
                    if (SVController.getCurrentViewId() != currentView.getId()) {
                        logger.info("Installing current view!");
                        SVController.reconfigureTo(currentView);
                    }
                    isInitializing = false;
                    dt.canDeliver();
                    dt.deliverUnlock();
                    reset();
                    logger.info("I updated the state!");
                    tomLayer.requestsTimer.Enabled(true);
                    tomLayer.requestsTimer.startTimer();
                    if (stateTimer != null) {
                        stateTimer.cancel();
                    }
                    if (appStateOnly) {
                        appStateOnly = false;
                        tomLayer.getSynchronizer().resumeLC();
                    }
                } else if (state == null && (SVController.getCurrentViewN() / 2) < getReplies()) {
                    logger.warn("---- DIDNT RECEIVE STATE ----");
                    logger.debug("I have more than " + (SVController.getCurrentViewN() / 2) + " messages that are no good!");
                    waitingCID = -1;
                    reset();
                    if (stateTimer != null) {
                        stateTimer.cancel();
                    }
                    if (appStateOnly) {
                        requestState();
                    }
                } else if (!haveState) {
                    logger.warn("---- RECEIVED INVALID STATE  ----");
                    logger.debug("The replica from which I expected the state, sent one which doesn't match the hash of the others, or it never sent it at all");
                    reset();
                    requestState();
                    if (stateTimer != null) {
                        stateTimer.cancel();
                    }
                }
            }
        }
    }
    lockTimer.unlock();
}
Also used : UnknownHostException(java.net.UnknownHostException) InetSocketAddress(java.net.InetSocketAddress) ApplicationState(bftsmart.statemanagement.ApplicationState) IOException(java.io.IOException) View(bftsmart.reconfiguration.views.View) DurabilityCoordinator(bftsmart.tom.server.durability.DurabilityCoordinator) ConsensusMessage(bftsmart.consensus.messages.ConsensusMessage) CommandsInfo(bftsmart.tom.server.defaultservices.CommandsInfo) Socket(java.net.Socket) ObjectInputStream(java.io.ObjectInputStream)

Example 22 with View

use of bftsmart.reconfiguration.views.View in project bftsmart by blockchain-jd-com.

the class ServiceProxy method invoke.

/**
 * This method sends a request to the replicas, and returns the related reply.
 * If the servers take more than invokeTimeout seconds the method returns null.
 * This method is thread-safe.
 *
 * @param request
 *            Request to be sent
 * @param reqType
 *            TOM_NORMAL_REQUESTS for service requests, and other for reconfig
 *            requests.
 * @return The reply from the replicas related to request
 */
public byte[] invoke(byte[] request, TOMMessageType reqType) {
    canSendLock.lock();
    try {
        // Clean all statefull data to prepare for receiving next replies
        Arrays.fill(replies, null);
        receivedReplies = 0;
        response = null;
        replyQuorum = getReplyQuorum();
        // Send the request to the replicas, and get its ID
        reqId = generateRequestId(reqType);
        operationId = generateOperationId();
        requestType = reqType;
        replyServer = -1;
        hashResponseController = null;
        LOGGER.info("Before Sending request {} with reqId {}, operationId {}, clientId={}", reqType, reqId, operationId, getProcessId());
        if (requestType == TOMMessageType.UNORDERED_HASHED_REQUEST) {
            replyServer = getRandomlyServerId();
            LOGGER.debug("[{}] replyServerId {} pos at {}", this.getClass().getName(), replyServer, getViewManager().getCurrentViewPos(replyServer));
            hashResponseController = new HashResponseController(getViewManager().getCurrentViewPos(replyServer), getViewManager().getCurrentViewProcesses().length);
            TOMMessage sm = new TOMMessage(getProcessId(), getSession(), reqId, operationId, request, null, getViewManager().getCurrentViewId(), requestType);
            sm.setReplyServer(replyServer);
            TOMulticast(sm);
        } else {
            TOMulticast(request, reqId, operationId, reqType);
        }
        LOGGER.info("After Sending request {} with reqId {}, operationId {}, clientId={}", reqType, reqId, operationId, getProcessId());
        LOGGER.debug("Expected number of matching replies: {}", replyQuorum);
        // by the client side communication system
        try {
            if (reqType == TOMMessageType.UNORDERED_HASHED_REQUEST) {
                if (!this.sm.tryAcquire(invokeUnorderedHashedTimeout, TimeUnit.SECONDS)) {
                    LOGGER.debug("######## UNORDERED HASHED REQUEST TIMOUT ########");
                    return invoke(request, TOMMessageType.ORDERED_REQUEST);
                }
            } else {
                if (!this.sm.tryAcquire(invokeTimeout, TimeUnit.SECONDS)) {
                    LOGGER.error("###################TIMEOUT#######################");
                    LOGGER.error("Reply timeout for reqId is {}", reqId);
                    LOGGER.error("Process id {} // req id {} // TIMEOUT // ", getProcessId(), reqId);
                    LOGGER.error("Replies received: {}", receivedReplies);
                    LOGGER.error("Replies quorum: {}", replyQuorum);
                    checkReplyNum(reqType, receivedReplies, replyQuorum);
                    return null;
                }
            }
        } catch (ViewObsoleteException voe) {
            throw voe;
        } catch (Exception ex) {
            LOGGER.error("exception", ex);
        }
        LOGGER.debug("Response extracted {}", response);
        byte[] ret = null;
        if (response == null) {
            // the response can be null if n-f replies are received but there isn't
            // a replyQuorum of matching replies
            LOGGER.error("Received n-f replies and no response could be extracted. request.length = {}, type = {} !", request.length, reqType);
            throw new RuntimeException("Received n-f replies without f+1 of them matching.");
        } else {
            // ******* EDUARDO BEGIN **************//
            if (reqType == TOMMessageType.ORDERED_REQUEST) {
                // Reply to a normal request!
                if (response.getViewID() == getViewManager().getCurrentViewId()) {
                    // return the response
                    ret = response.getContent();
                } else {
                    // if(response.getViewID() > getViewManager().getCurrentViewId())
                    // Request with backward viewid, still up chain by server node, but proxy client need update local view according to response view
                    LOGGER.warn("Service proxy view id little than service replica view id, will update local view!");
                    if (response.getViewContent() != null) {
                        reconfigureTo((View) TOMUtil.getObject(response.getViewContent()));
                    }
                    ret = response.getContent();
                // LOGGER.warn("Service proxy view id little than service replica view id, will re invoke request!");
                // return invoke(request, reqType);
                }
            } else if (reqType == TOMMessageType.UNORDERED_REQUEST || reqType == TOMMessageType.UNORDERED_HASHED_REQUEST) {
                // return the response
                ret = response.getContent();
                if (response.getViewID() > getViewManager().getCurrentViewId()) {
                    Object r = TOMUtil.getObject(response.getContent());
                    if (r instanceof View) {
                        reconfigureTo((View) r);
                        return invoke(request, reqType);
                    }
                }
            } else {
                if (response.getViewID() > getViewManager().getCurrentViewId()) {
                    // Reply to a reconfigure request!
                    LOGGER.debug("Reconfiguration request' reply received!");
                    Object r = TOMUtil.getObject(response.getContent());
                    if (r instanceof View) {
                        // did not executed the request because it is using an outdated view
                        reconfigureTo((View) r);
                        return invoke(request, reqType);
                    } else if (r instanceof ReconfigureReply) {
                        // reconfiguration executed!
                        reconfigureTo(((ReconfigureReply) r).getView());
                        ret = response.getContent();
                    } else {
                        LOGGER.error("Unknown response type");
                    }
                } else {
                    LOGGER.error("Unexpected execution flow");
                }
            }
        }
        return ret;
    } catch (Exception e) {
        LOGGER.error("[ServiceProxy] invoke exception occur!", e);
        throw e;
    } finally {
        canSendLock.unlock();
    }
}
Also used : TOMMessage(bftsmart.tom.core.messages.TOMMessage) ReconfigureReply(bftsmart.reconfiguration.ReconfigureReply) ViewObsoleteException(utils.exception.ViewObsoleteException) View(bftsmart.reconfiguration.views.View) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) ViewObsoleteException(utils.exception.ViewObsoleteException)

Example 23 with View

use of bftsmart.reconfiguration.views.View in project bftsmart by blockchain-jd-com.

the class ServiceReplica method receiveReadonlyMessage.

/**
 * This message delivers a readonly message, i.e., a message that was not
 * ordered to the replica and gather the reply to forward to the client
 *
 * @param message the request received from the delivery thread
 */
public final void receiveReadonlyMessage(TOMMessage message, MessageContext msgCtx) {
    byte[] response = null;
    // applications to log it or keep any proof.
    if (executor instanceof FIFOExecutable) {
        response = ((FIFOExecutable) executor).executeUnorderedFIFO(message.getContent(), msgCtx, message.getSender(), message.getOperationId());
    } else {
        if (message.getViewID() == serverViewController.getCurrentViewId()) {
            response = executor.executeUnordered(message.getContent(), msgCtx);
        } else if (message.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(), inetSocketAddress.getMonitorPort(), inetSocketAddress.isConsensusSecure(), inetSocketAddress.isMonitorSecure());
                    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);
                    addressesTemp.add(inetSocketAddress);
                }
            }
            View replyView = new View(view.getId(), view.getProcesses(), view.getF(), addressesTemp.toArray(new NodeNetwork[addressesTemp.size()]));
            response = TOMUtil.getBytes(replyView);
        }
    }
    if (message.getReqType() == TOMMessageType.UNORDERED_HASHED_REQUEST && message.getReplyServer() != this.id) {
        try {
            response = TOMUtil.computeHash(response);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
    }
    // Generate the messages to send back to the clients
    message.reply = new TOMMessage(id, message.getSession(), message.getSequence(), message.getOperationId(), response, null, serverViewController.getCurrentViewId(), message.getReqType());
    if (serverViewController.getStaticConf().getNumRepliers() > 0) {
        repMan.send(message);
    } else {
        cs.send(new int[] { message.getSender() }, message.reply);
    }
}
Also used : TOMMessage(bftsmart.tom.core.messages.TOMMessage) FIFOExecutable(bftsmart.tom.server.FIFOExecutable) ArrayList(java.util.ArrayList) List(java.util.List) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) View(bftsmart.reconfiguration.views.View) NodeNetwork(bftsmart.reconfiguration.views.NodeNetwork)

Example 24 with View

use of bftsmart.reconfiguration.views.View in project bftsmart by blockchain-jd-com.

the class Synchronizer method beginElection.

/**
 * 由于收到其它节点报告的 STOP 消息数量达到了满足开始选举的数量条件,调用此方法将开始一轮新的选举;
 *
 * <p>
 *
 * 1. 调用此方法时,如果当前节点尚未开启新选举,则此方法将开启新一轮选举,并向其它节点广播 STOP / STOP_APPEND 消息;<br>
 * 1.1. 如果开启选举的提议( {@link LeaderRegencyPropose} )来自当前节点,则向其它节点广播 STOP 消息; <br>
 * 1.2. 如果开启选举的提议( {@link LeaderRegencyPropose} )来自其它节点,则向其它节点广播 STOP_APPEND 消息;
 * <p>
 *
 * 2. 调用此方法时,如果当前节点已经开启新选举,则不做任何操作;
 */
private void beginElection(LeaderRegencyPropose regencyPropose) {
    if (!lcManager.tryBeginElection(regencyPropose.getRegency())) {
        return;
    }
    final boolean FROM_REMOTE = regencyPropose.getSender() != getCurrentId();
    final int PROPOSED_NEXT_REGENCY_ID = regencyPropose.getRegency().getId();
    heartBeatTimer.stopAll();
    requestsTimer.stopTimer();
    this.getLCManager().setLcTimestampStatePair(new LCTimestampStatePair(System.currentTimeMillis(), LCState.LC_SELECTING));
    // 加入当前节点的领导者执政期提议;
    // store information about message I am going to send
    lcManager.addStop(regencyPropose);
    // 对于已经收到满足f+1条件stop的情形,本身会发送stop_append, 定时器停止,不会再触发超时,此时需要把自己的投票
    LeaderRegencyPropose leaderRegencyPropose = LeaderRegencyPropose.copy(regencyPropose.getRegency().getLeaderId(), regencyPropose.getRegency().getId(), this.controller.getCurrentView().getId(), this.controller.getCurrentView().getProcesses(), getCurrentId());
    lcManager.addStop(leaderRegencyPropose);
    // Get requests that timed out and the requests received in STOP messages
    // and add those STOPed requests to the client manager
    addSTOPedRequestsToClientManager();
    try {
        // serialize conent to send in the STOP message
        byte[] payload = makeTomMessageReplyBatch(PROPOSED_NEXT_REGENCY_ID);
        if (FROM_REMOTE) {
            View currentView = this.controller.getCurrentView();
            if (!regencyPropose.isViewEquals(currentView)) {
                throw new IllegalStateException(String.format("The view of regency propose from node[%s] is not equal the the current view of node[%s]!", regencyPropose.getSender(), controller.getStaticConf().getProcessId()));
            }
            LCMessage msgSTOP_APPEND = LCMessage.createSTOP_APPEND(this.controller.getStaticConf().getProcessId(), regencyPropose.getRegency(), currentView, payload);
            // make replica re-transmit the stop
            requestsTimer.setSTOP(PROPOSED_NEXT_REGENCY_ID, msgSTOP_APPEND);
            // message
            // until a
            // new
            // regency is installed
            communication.send(this.controller.getCurrentViewOtherAcceptors(), msgSTOP_APPEND);
        } else {
            LCMessage msgSTOP = LCMessage.createSTOP(this.controller.getStaticConf().getProcessId(), regencyPropose.getRegency(), this.controller.getCurrentView(), payload);
            // TODO: ???
            // make replica re-transmit the stop message
            requestsTimer.setSTOP(PROPOSED_NEXT_REGENCY_ID, msgSTOP);
            // until a
            // new
            // regency is installed
            communication.send(this.controller.getCurrentViewOtherAcceptors(), msgSTOP);
        }
    } catch (Exception ex) {
        ex.printStackTrace();
        java.util.logging.Logger.getLogger(TOMLayer.class.getName()).log(Level.SEVERE, null, ex);
    }
}
Also used : LeaderRegencyPropose(bftsmart.tom.leaderchange.LeaderRegencyPropose) LCMessage(bftsmart.tom.leaderchange.LCMessage) LCTimestampStatePair(bftsmart.tom.leaderchange.LCTimestampStatePair) View(bftsmart.reconfiguration.views.View) IOException(java.io.IOException) EOFException(java.io.EOFException)

Example 25 with View

use of bftsmart.reconfiguration.views.View in project bftsmart by blockchain-jd-com.

the class StandardStateManager method SMReplyDeliver.

@Override
public void SMReplyDeliver(SMMessage msg, boolean isBFT) {
    LOGGER.info("I will handle SMReplyDeliver !");
    lockTimer.lock();
    if (topology.getStaticConf().isStateTransferEnabled()) {
        if (waitingCID != -1 && msg.getCID() == waitingCID) {
            int currentRegency = -1;
            int currentLeader = -1;
            View currentView = null;
            CertifiedDecision currentProof = null;
            if (!appStateOnly) {
                // TODO: 未正确更新 regency 和 leader;
                // senderRegencies.put(msg.getSender(), msg.getRegency());
                // senderLeaders.put(msg.getSender(), msg.getLeader());
                senderViews.put(msg.getSender(), msg.getView());
                senderProofs.put(msg.getSender(), msg.getState().getCertifiedDecision(topology));
                senderStates.put(msg.getSender(), msg.getState());
                // if (enoughLeaders(msg.getLeader())) currentLeader = msg.getLeader();
                if (enoughViews(msg.getView()))
                    currentView = msg.getView();
                if (enoughProofs(waitingCID, this.tomLayer.getSynchronizer().getLCManager()))
                    currentProof = msg.getState().getCertifiedDecision(topology);
                if (enoughState(msg.getState()))
                    state = msg.getState();
            } else {
                currentLeader = tomLayer.execManager.getCurrentLeader();
                currentRegency = tomLayer.getSynchronizer().getLCManager().getLastReg();
                currentView = topology.getCurrentView();
            }
            // 待优化处理
            // if (msg.getSender() == replica && msg.getState().getSerializedState() != null) {
            // LOGGER.info("Expected replica sent state. Setting it to state");
            // state = msg.getState();
            // if (stateTimer != null) stateTimer.cancel();
            // }
            LOGGER.info("Verifying more than Quorum consistent replies");
            if (state != null) {
                LOGGER.info("More than Quorum consistent confirmed");
                ApplicationState otherReplicaState = getOtherReplicaState();
                LOGGER.info("State != null: {}, recvState != null: {}", (state != null), (otherReplicaState != null));
                int haveState = 0;
                // if(state != null) {
                byte[] hash = null;
                hash = tomLayer.computeHash(state.getSerializedState());
                if (otherReplicaState != null) {
                    if (Arrays.equals(hash, otherReplicaState.getStateHash()))
                        haveState = 1;
                    else if (getNumEqualStates() > topology.getCurrentViewF())
                        haveState = -1;
                }
                // }
                LOGGER.debug("haveState: {}", haveState);
                if (otherReplicaState != null && haveState == 1 && currentView != null) {
                    LOGGER.debug("Received state. Will install it");
                    if (currentProof != null && !appStateOnly) {
                        LOGGER.debug("Installing proof for consensus {}", waitingCID);
                        Consensus cons = execManager.getConsensus(waitingCID);
                        Epoch e = null;
                        for (ConsensusMessage cm : currentProof.getConsMessages()) {
                            e = cons.getEpoch(cm.getEpoch(), true, topology);
                            if (e.getTimestamp() != cm.getEpoch()) {
                                LOGGER.debug("Strange... proof contains messages from more than just one epoch");
                                e = cons.getEpoch(cm.getEpoch(), true, topology);
                            }
                            e.addToProof(cm);
                            if (cm.getType() == MessageFactory.ACCEPT) {
                                e.setAccept(cm.getSender(), cm.getValue());
                            } else if (cm.getType() == MessageFactory.WRITE) {
                                e.setWrite(cm.getSender(), cm.getValue());
                            }
                        }
                        if (e != null) {
                            hash = tomLayer.computeHash(currentProof.getDecision());
                            e.propValueHash = hash;
                            e.propValue = currentProof.getDecision();
                            e.deserializedPropValue = tomLayer.checkProposedValue(currentProof.getDecision(), false);
                            cons.decided(e, false);
                            LOGGER.debug("Successfully installed proof for consensus {}", waitingCID);
                        } else {
                            LOGGER.error("Failed to install proof for consensus {}", waitingCID);
                        }
                    }
                    // I might have timed out before invoking the state transfer, so
                    // stop my re-transmission of STOP messages for all regencies up to the current one
                    // if (currentRegency > 0) tomLayer.getSynchronizer().removeSTOPretransmissions(currentRegency - 1);
                    // if (currentRegency > 0)
                    // tomLayer.requestsTimer.setTimeout(tomLayer.requestsTimer.getTimeout() * (currentRegency * 2));
                    dt.deliverLock();
                    waitingCID = -1;
                    dt.update(state);
                    if (topology.getCurrentViewId() <= currentView.getId()) {
                        LOGGER.info("Installing current view!");
                        // 当通过交易重放回补落后区块时,不仅要更新本地视图,还需要同时更新本地的hostconfig
                        topology.reconfigureTo(currentView);
                        updateHostConfig(currentView);
                    }
                    isInitializing = false;
                    // trigger out of context propose msg process
                    tomLayer.processOutOfContext();
                    dt.canDeliver();
                    dt.deliverUnlock();
                    reset();
                    LOGGER.info("I updated the state!");
                    // 有差异的话,完成后会走此流程
                    tomLayer.connectRemotesOK();
                    // tomLayer.requestsTimer.startTimer();
                    if (stateTimer != null)
                        stateTimer.cancel();
                    if (appStateOnly) {
                        appStateOnly = false;
                        tomLayer.getSynchronizer().resumeLC();
                    }
                } else if (otherReplicaState == null && (topology.getCurrentViewN() / 2) < getReplies()) {
                    LOGGER.info("otherReplicaState == null && (SVController.getCurrentViewN() / 2) < getReplies()");
                    waitingCID = -1;
                    reset();
                    if (stateTimer != null)
                        stateTimer.cancel();
                    if (appStateOnly) {
                        requestState();
                    }
                } else if (haveState == -1) {
                    LOGGER.error("haveState == -1");
                    LOGGER.error("(TOMLayer.SMReplyDeliver) The replica from which I expected the state, sent one which doesn't match the hash of the others, or it never sent it at all");
                    changeReplica();
                    reset();
                    requestState();
                    if (stateTimer != null)
                        stateTimer.cancel();
                } else if (haveState == 0 && (topology.getCurrentViewN() - topology.getCurrentViewF()) <= getReplies()) {
                    LOGGER.error("(TOMLayer.SMReplyDeliver) Could not obtain the state, retrying");
                    reset();
                    if (stateTimer != null)
                        stateTimer.cancel();
                    waitingCID = -1;
                // requestState();
                } else {
                    LOGGER.debug(" -- State transfer not yet finished");
                }
            }
        }
    }
    lockTimer.unlock();
}
Also used : CertifiedDecision(bftsmart.tom.leaderchange.CertifiedDecision) ConsensusMessage(bftsmart.consensus.messages.ConsensusMessage) ApplicationState(bftsmart.statemanagement.ApplicationState) Epoch(bftsmart.consensus.Epoch) View(bftsmart.reconfiguration.views.View) Consensus(bftsmart.consensus.Consensus)

Aggregations

View (bftsmart.reconfiguration.views.View)32 NodeNetwork (bftsmart.reconfiguration.views.NodeNetwork)10 TOMMessage (bftsmart.tom.core.messages.TOMMessage)7 ConsensusMessage (bftsmart.consensus.messages.ConsensusMessage)5 ArrayList (java.util.ArrayList)5 TOMConfiguration (bftsmart.reconfiguration.util.TOMConfiguration)4 ApplicationState (bftsmart.statemanagement.ApplicationState)4 IOException (java.io.IOException)4 MemoryBasedViewStorage (bftsmart.reconfiguration.views.MemoryBasedViewStorage)3 Properties (java.util.Properties)3 ReplyListener (bftsmart.communication.client.ReplyListener)2 Consensus (bftsmart.consensus.Consensus)2 Epoch (bftsmart.consensus.Epoch)2 ReconfigureReply (bftsmart.reconfiguration.ReconfigureReply)2 HostsConfig (bftsmart.reconfiguration.util.HostsConfig)2 AsynchServiceProxy (bftsmart.tom.AsynchServiceProxy)2 ViewMessage (bftsmart.tom.core.messages.ViewMessage)2 CertifiedDecision (bftsmart.tom.leaderchange.CertifiedDecision)2 LCMessage (bftsmart.tom.leaderchange.LCMessage)2 LeaderRegency (bftsmart.tom.leaderchange.LeaderRegency)2