if(new_mbrs.isEmpty() && leaving_mbrs.isEmpty() && suspected_mbrs.isEmpty()) {
log.trace("%s: found no members to add or remove, will not create new view", gms.local_addr);
return;
}
View new_view=gms.getNextView(new_mbrs, leaving_mbrs, suspected_mbrs);
if(new_view.size() == 0 && gms.local_addr != null && gms.local_addr.equals(new_view.getCreator())) {
if(self_leaving)
gms.initState(); // in case connect() is called again
return;
}
log.trace("%s: joiners=%s, suspected=%s, leaving=%s, new view: %s",
gms.local_addr, new_mbrs, suspected_mbrs, leaving_mbrs, new_view);
JoinRsp join_rsp=null;
boolean hasJoiningMembers=!new_mbrs.isEmpty();
try {
boolean successfulFlush =!useFlushIfPresent || !gms.flushProtocolInStack || gms.startFlush(new_view);
if(!successfulFlush && hasJoiningMembers) {
// Don't send a join response if the flush fails (http://jira.jboss.org/jira/browse/JGRP-759)
// The joiner should block until the previous FLUSH completed
sendLeaveResponses(leaving_mbrs); // we still have to send potential leave responses
// but let the joining client timeout and send another join request
return;
}
// we cannot garbage collect during joining a new member *if* we're the only member
// Example: {A}, B joins, after returning JoinRsp to B, A garbage collects messages higher than those
// in the digest returned to the client, so the client will *not* be able to ask for retransmission
// of those messages if he misses them
if(hasJoiningMembers) {
gms.getDownProtocol().down(new Event(Event.SUSPEND_STABLE, MAX_SUSPEND_TIMEOUT));
// create a new digest, which contains the new members, minus left members
MutableDigest join_digest=new MutableDigest(new_view.getMembersRaw()).set(gms.getDigest());
for(Address member: new_mbrs)
join_digest.set(member,0,0); // ... and set the new members. their first seqno will be 1
// If the digest from NAKACK doesn't include all members of the view, we try once more; if it is still
// incomplete, we don't send a JoinRsp back to the joiner(s). This shouldn't be a problem as they will retry