void becomeSingletonMember(Address mbr) { View new_view=View.create(mbr, 0, mbr); // create singleton view with mbr as only member // set the initial digest (since I'm the first member) Digest initial_digest=new Digest(mbr, 0, 0); gms.installView(new_view, initial_digest); gms.becomeCoordinator(); // not really necessary - installView() should do it gms.getUpProtocol().up(new Event(Event.BECOME_SERVER)); gms.getDownProtocol().down(new Event(Event.BECOME_SERVER)); log.debug("%s: created cluster (first member). My view is %s, impl is %s", gms.getLocalAddress(), gms.getViewId(), gms.getImpl().getClass().getName()); } }
/** The coordinator itself wants to leave the group */ public void leave(Address mbr) { if(mbr == null) { if(log.isErrorEnabled()) log.error(Util.getMessage("MemberSAddressIsNull")); return; } leaving=true; Address next_coord=gms.determineNextCoordinator(); if(next_coord != null) sendLeaveReqTo(next_coord); else { gms.getViewHandler().add(new Request(Request.LEAVE, mbr)); // If we're the coord leaving, ignore gms.leave_timeout: https://issues.jboss.org/browse/JGRP-1509 long timeout=(long)(Math.max(gms.leave_timeout, gms.view_ack_collection_timeout) * 1.10); gms.getViewHandler().waitUntilComplete(timeout); } gms.becomeClient(); }
mergeDigest(digest); else setDigest(digest); Address coord=determineCoordinator(); if(coord != null && coord.equals(local_addr) && !haveCoordinatorRole()) { becomeCoordinator(); if(haveCoordinatorRole() && !local_addr.equals(coord)) { becomeParticipant();
/** * Loop: determine coord. If coord is me --> handleLeave(). * Else send handleLeave() to coord until success */ public void leave(Address mbr) { Address coord=gms.determineCoordinator(); if(coord != null) sendLeaveReqTo(coord); gms.becomeClient(); }
/** * Called by join(). Installs the view returned by calling Coord.handleJoin() and becomes coordinator. */ private boolean installView(View new_view, Digest digest) { if(!new_view.containsMember(gms.local_addr)) { log.error("%s: I'm not member of %s, will not install view", gms.local_addr, new_view); return false; } gms.installView(new_view, digest); if(gms.impl == null || gms.impl instanceof ClientGmsImpl) // installView() should have set the role (impl) gms.becomeParticipant(); gms.getUpProtocol().up(new Event(Event.BECOME_SERVER)); gms.getDownProtocol().down(new Event(Event.BECOME_SERVER)); return true; }
if(gms.getViewId() == null) { if(gms.members.contains(mbr)) { // already joined: return current digest and membership log.trace("%s: %s already present; returning existing view %s", gms.local_addr, mbr, gms.view); Tuple<View,Digest> tuple=gms.getViewAndDigest(); if(tuple != null) gms.sendJoinResponse(new JoinRsp(tuple.getVal1(), tuple.getVal2()), mbr); else log.warn("%s: did not find a digest matching view %s; dropping JOIN-RSP", gms.local_addr, gms.view); View new_view=gms.getNextView(new_mbrs, leaving_mbrs, suspected_mbrs); gms.initState(); // in case connect() is called again return; boolean hasJoiningMembers=!new_mbrs.isEmpty(); try { boolean successfulFlush =!useFlushIfPresent || !gms.flushProtocolInStack || gms.startFlush(new_view); if(!successfulFlush && hasJoiningMembers) { gms.getDownProtocol().down(new Event(Event.SUSPEND_STABLE, MAX_SUSPEND_TIMEOUT)); 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(join_digest.allSet() || join_digest.set(gms.getDigest()).allSet()) join_rsp=new JoinRsp(new_view, join_digest); else
if(log.isWarnEnabled()) log.warn(mbr + " already present; returning existing view " + gms.view); JoinRsp join_rsp=new JoinRsp(new View(gms.view_id, gms.members.getMembers()), gms.getDigest()); sendJoinResponse(join_rsp, mbr); it.remove(); View new_view=gms.getNextView(new_mbrs, leaving_mbrs, suspected_mbrs); if(log.isDebugEnabled()) log.debug("new=" + new_mbrs + ", suspected=" + suspected_mbrs + ", leaving=" + leaving_mbrs + gms.getDownProtocol().down(new Event(Event.SUSPEND_STABLE, MAX_SUSPEND_TIMEOUT)); Digest tmp=gms.getDigest(); // get existing digest MutableDigest join_digest=null; if(tmp == null) boolean successfulFlush = gms.startFlush(new_view,4000); if (successfulFlush){ if(log.isTraceEnabled()) log.trace("Successful GMS flush by coordinator at " + gms.getLocalAddress()); log.warn("GMS flush by coordinator at " + gms.getLocalAddress() + " failed"); gms.castViewChangeWithDest(new_view, null, tmp_mbrs); gms.castViewChangeWithDest(new_view, null, tmp_mbrs); gms.getDownProtocol().down(new Event(Event.RESUME_STABLE)); if(gms.flushProtocolInStack) gms.stopFlush(new_view);
void becomeSingletonMember(Address mbr) { Digest initial_digest; ViewId view_id; Vector mbrs=new Vector(1); // set the initial digest (since I'm the first member) initial_digest=new Digest(gms.local_addr, 0, 0); // initial seqno mcast by me will be 1 (highest seen +1) gms.setDigest(initial_digest); view_id=new ViewId(mbr); // create singleton view with mbr as only member mbrs.addElement(mbr); gms.installView(new View(view_id, mbrs)); gms.becomeCoordinator(); // not really necessary - installView() should do it gms.getUpProtocol().up(new Event(Event.BECOME_SERVER)); gms.getDownProtocol().down(new Event(Event.BECOME_SERVER)); if(log.isDebugEnabled()) log.debug("created group (first member). My view is " + gms.view_id + ", impl is " + gms.getImpl().getClass().getName()); }
protected void sendMergeCancelledMessage(Collection<Address> coords, MergeId merge_id) { if(coords == null || merge_id == null) return; for(Address coord: coords) { Message msg=new Message(coord).putHeader(gms.getId(), new GMS.GmsHeader(GMS.GmsHeader.CANCEL_MERGE).mergeId(merge_id)); gms.getDownProtocol().down(msg); } }
/** * Fetches the digests from all members and installs them again. Used only for diagnosis and support; don't * use this otherwise ! */ protected void fixDigests() { Digest digest=fetchDigestsFromAllMembersInSubPartition(gms.view, null); Message msg=new Message().putHeader(gms.getId(), new GMS.GmsHeader(GMS.GmsHeader.INSTALL_DIGEST)) .setBuffer(GMS.marshal(null, digest)); gms.getDownProtocol().down(msg); }
public void installView(View new_view) { installView(new_view,null); }
mergeDigest(digest); if(checkSelfInclusion(mbrs) == false) { coord=determineCoordinator(); if(coord != null && coord.equals(local_addr) && !haveCoordinatorRole()) { becomeCoordinator(); if(haveCoordinatorRole() && !local_addr.equals(coord)) becomeParticipant();
/** * Loop: determine coord. If coord is me --> handleLeave(). * Else send handleLeave() to coord until success */ public void leave(Address mbr) { Address coord; int max_tries=3; Object result; leave_promise.reset(); if(mbr.equals(gms.local_addr)) leaving=true; while((coord=gms.determineCoordinator()) != null && max_tries-- > 0) { if(gms.local_addr.equals(coord)) { // I'm the coordinator gms.becomeCoordinator(); // gms.getImpl().handleLeave(mbr, false); // regular leave gms.getImpl().leave(mbr); // regular leave return; } if(log.isDebugEnabled()) log.debug("sending LEAVE request to " + coord + " (local_addr=" + gms.local_addr + ")"); sendLeaveMessage(coord, mbr); result=leave_promise.getResult(gms.leave_timeout); if(result != null) break; } gms.becomeClient(); }
protected synchronized void cancelMerge(MergeId id) { if(setMergeId(id, null)) { merge_task.stop(); stopMergeKiller(); merge_rsps.reset(); gms.getViewHandler().resume(); gms.getDownProtocol().down(new Event(Event.RESUME_STABLE)); } }
public void handleMembershipChange(Collection<Request> requests) { Collection<Address> leaving_mbrs=new LinkedHashSet<>(requests.size()); requests.forEach(r -> { if(r.type == Request.SUSPECT) suspected_mbrs.add(r.mbr); else if(r.type == Request.LEAVE) leaving_mbrs.add(r.mbr); }); if(suspected_mbrs.isEmpty() && leaving_mbrs.isEmpty()) return; if(wouldIBeCoordinator(leaving_mbrs)) { log.debug("%s: members are %s, coord=%s: I'm the new coordinator", gms.local_addr, gms.members, gms.local_addr); gms.becomeCoordinator(); Collection<Request> leavingOrSuspectedMembers=new LinkedHashSet<>(); leaving_mbrs.forEach(mbr -> leavingOrSuspectedMembers.add(new Request(Request.LEAVE, mbr))); suspected_mbrs.forEach(mbr -> { leavingOrSuspectedMembers.add(new Request(Request.SUSPECT, mbr)); gms.ack_collector.suspect(mbr); }); suspected_mbrs.clear(); gms.getViewHandler().add(leavingOrSuspectedMembers); } }
try { if(flushProtocolInStack) { boolean successfulFlush = startFlush(firstReq.view,4000); if (successfulFlush){ if(log.isTraceEnabled()) log.trace("Successful GMS flush by coordinator at " + getLocalAddress()); log.warn("GMS flush by coordinator at " + getLocalAddress() + " failed"); castViewChangeWithDest(firstReq.view, firstReq.digest, firstReq.target_members); stopFlush(firstReq.view);
/** * If merge_id is not equal to this.merge_id then discard. Else cast the view/digest to all members of this group. */ public void handleMergeView(final MergeData data, final MergeId merge_id) { if(!matchMergeId(merge_id)) { log.trace("%s: merge_ids (mine: %s, received: %s) don't match; merge view %s is discarded", gms.local_addr, this.merge_id, merge_id, data.view.getViewId()); return; } // only send to our *current* members, if we have A and B being merged (we are B), then we would *not* // want to block on a VIEW_ACK from A because A doesn't see us in the pre-merge view yet and discards the view List<Address> expected_acks=gms.members.getMembers(); try { gms.castViewChangeAndSendJoinRsps(data.view, data.digest, expected_acks, null, null); // if we have flush in stack send ack back to merge coordinator if(gms.flushProtocolInStack) { //[JGRP-700] - FLUSH: flushing should span merge Message ack=new Message(data.getSender()).setFlag(Message.Flag.OOB, Message.Flag.INTERNAL) .putHeader(gms.getId(), new GMS.GmsHeader(GMS.GmsHeader.INSTALL_MERGE_VIEW_OK)); gms.getDownProtocol().down(ack); } } finally { cancelMerge(merge_id); } }
private void sendLeaveResponses(Collection c) { for(Iterator i=c.iterator(); i.hasNext();) { Message msg=new Message((Address)i.next(), null, null); // send an ack to the leaving member GMS.GmsHeader hdr=new GMS.GmsHeader(GMS.GmsHeader.LEAVE_RSP); msg.putHeader(gms.getName(), hdr); gms.getDownProtocol().down(new Event(Event.MSG, msg)); } }
/** In case we get a different JOIN_RSP from a previous JOIN_REQ sent by us (as a client), we simply apply the * new view if it is greater than ours * * @param join_rsp */ public void handleJoinResponse(JoinRsp join_rsp) { View v=join_rsp.getView(); ViewId tmp_vid=v != null? v.getViewId() : null; ViewId my_view=gms.getViewId(); if(tmp_vid != null && my_view != null && tmp_vid.compareToIDs(my_view) > 0) { Digest d=join_rsp.getDigest(); gms.installView(v, d); } }
protected GmsImpl(GMS gms) { this.gms=gms; merger=gms.merger; log=gms.getLog(); }