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();
}
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();
}
}
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);
}
}
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);
}
}
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();
}
Aggregations