use of org.jgroups.View in project JGroups by belaban.
the class CoordGmsImpl method handleMembershipChange.
public void handleMembershipChange(Collection<Request> requests) {
boolean joinAndStateTransferInitiated = false;
boolean useFlushIfPresent = gms.use_flush_if_present;
Collection<Address> new_mbrs = new LinkedHashSet<>(requests.size());
Collection<Address> suspected_mbrs = new LinkedHashSet<>(requests.size());
Collection<Address> leaving_mbrs = new LinkedHashSet<>(requests.size());
// is the coord leaving
boolean self_leaving = false;
for (Request req : requests) {
switch(req.type) {
case Request.JOIN:
new_mbrs.add(req.mbr);
if (req.useFlushIfPresent)
useFlushIfPresent = true;
break;
case Request.JOIN_WITH_STATE_TRANSFER:
new_mbrs.add(req.mbr);
joinAndStateTransferInitiated = true;
if (req.useFlushIfPresent)
useFlushIfPresent = true;
break;
case Request.LEAVE:
leaving_mbrs.add(req.mbr);
if (Objects.equals(gms.local_addr, req.mbr))
self_leaving = true;
break;
case Request.SUSPECT:
suspected_mbrs.add(req.mbr);
break;
}
}
// remove myself - cannot join myself (already joined)
new_mbrs.remove(gms.local_addr);
if (gms.getViewId() == null) {
// we're probably not the coord anymore (we just left ourselves), let someone else do it
// (client will retry when it doesn't get a response)
log.debug("gms.view_id is null, I'm not the coordinator anymore (leaving=%b); " + "the new coordinator will handle the leave request", self_leaving);
return;
}
List<Address> current_members = gms.members.getMembers();
// remove all elements of leaving_mbrs which are not current members
leaving_mbrs.retainAll(current_members);
if (suspected_mbrs.remove(gms.local_addr))
log.warn("I am the coord and I'm being suspected -- will probably leave shortly");
// remove all elements of suspected_mbrs which are not current members
suspected_mbrs.retainAll(current_members);
// for the members that have already joined, return the current digest and membership
for (Iterator<Address> it = new_mbrs.iterator(); it.hasNext(); ) {
Address mbr = it.next();
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);
// remove it anyway, even if we didn't find a digest matching the view (joiner will retry)
it.remove();
}
}
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)
// in case connect() is called again
gms.initState();
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
// we still have to send potential leave responses
sendLeaveResponses(leaving_mbrs);
// but let the joining client timeout and send another join request
return;
}
// 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) // ... and set the new members. their first seqno will be 1
join_digest.set(member, 0, 0);
// incomplete, we don't send a JoinRsp back to the joiner(s). This shouldn't be a problem as they will retry
if (join_digest.allSet() || join_digest.set(gms.getDigest()).allSet())
join_rsp = new JoinRsp(new_view, join_digest);
else
log.warn("%s: digest does not match view (missing seqnos for %s); dropping JOIN-RSP", gms.local_addr, Arrays.toString(join_digest.getNonSetMembers()));
}
// no-op if no leaving members
sendLeaveResponses(leaving_mbrs);
// we don't need to send the digest to existing members: https://issues.jboss.org/browse/JGRP-1317
gms.castViewChangeAndSendJoinRsps(new_view, null, new_view.getMembers(), new_mbrs, join_rsp);
} finally {
if (hasJoiningMembers)
gms.getDownProtocol().down(new Event(Event.RESUME_STABLE));
if (!joinAndStateTransferInitiated && useFlushIfPresent)
gms.stopFlush();
if (self_leaving)
// in case connect() is called again
gms.initState();
}
}
use of org.jgroups.View in project JGroups by belaban.
the class DeliveryManagerImpl method getAndSetView.
@GuardedBy("deliverySet")
private View getAndSetView(View newView) {
View oldView = currentView;
currentView = newView;
return oldView;
}
use of org.jgroups.View in project JGroups by belaban.
the class GroupRequest method viewChange.
/**
* Any member of 'membership' that is not in the new view is flagged as SUSPECTED. Any member in the new view that
* is <em>not</em> in the membership (ie, the set of responses expected for the current RPC) will <em>not</em> be
* added to it. If we did this we might run into the following problem:
* <ul>
* <li>Membership is {A,B}
* <li>A sends a synchronous group RPC (which sleeps for 60 secs in the invocation handler)
* <li>C joins while A waits for responses from A and B
* <li>If this would generate a new view {A,B,C} and if this expanded the response set to {A,B,C}, A would wait
* forever on C's response because C never received the request in the first place, therefore won't send a response.
* </ul>
*/
public void viewChange(View view, boolean handle_previous_subgroups) {
if (view == null || rsps == null || rsps.isEmpty())
return;
boolean changed = false;
lock.lock();
try {
if (view instanceof MergeView && handle_previous_subgroups) {
// unless that rsp has already been received (https://issues.redhat.com/browse/JGRP-2575)
for (View v : ((MergeView) view).getSubgroups()) {
if (!v.containsMember(corr.local_addr)) {
for (Address mbr : v.getMembersRaw()) if (setSuspected(mbr))
changed = true;
}
}
}
for (Map.Entry<Address, Rsp<T>> entry : rsps.entrySet()) {
Address mbr = entry.getKey();
// SiteAddresses are not checked as they might be in a different cluster
if (!(mbr instanceof SiteAddress) && !view.containsMember(mbr)) {
Rsp<T> rsp = entry.getValue();
if (rsp.setSuspected()) {
if (!(rsp.wasReceived() || rsp.wasUnreachable()))
num_received++;
changed = true;
}
}
}
if (changed && responsesComplete()) {
complete(this.rsps);
corrDone();
}
} finally {
lock.unlock();
}
}
use of org.jgroups.View in project JGroups by belaban.
the class PDC method down.
public Object down(Event evt) {
switch(evt.getType()) {
case Event.GET_PHYSICAL_ADDRESS:
Object addr = down_prot.down(evt);
Address arg = evt.getArg();
return addr != null ? addr : cache.get(arg);
case Event.GET_PHYSICAL_ADDRESSES:
Collection<PhysicalAddress> addrs = (Collection<PhysicalAddress>) down_prot.down(evt);
Collection<PhysicalAddress> tmp = new HashSet<>(addrs);
tmp.addAll(cache.values());
return tmp;
case Event.GET_LOGICAL_PHYSICAL_MAPPINGS:
Map<Address, PhysicalAddress> map = (Map<Address, PhysicalAddress>) down_prot.down(evt);
Map<Address, PhysicalAddress> new_map = new HashMap<>(map);
new_map.putAll(cache);
return new_map;
case Event.ADD_PHYSICAL_ADDRESS:
Tuple<Address, PhysicalAddress> new_val = evt.getArg();
if (new_val != null) {
cache.put(new_val.getVal1(), new_val.getVal2());
writeNodeToDisk(new_val.getVal1(), new_val.getVal2());
}
break;
case Event.REMOVE_ADDRESS:
Address tmp_addr = evt.getArg();
if (cache.remove(tmp_addr) != null)
removeNodeFromDisk(tmp_addr);
break;
case Event.VIEW_CHANGE:
List<Address> members = ((View) evt.getArg()).getMembers();
cache.keySet().stream().filter(mbr -> !members.contains(mbr)).forEach(mbr -> {
cache.remove(mbr);
removeNodeFromDisk(mbr);
});
break;
}
return down_prot.down(evt);
}
use of org.jgroups.View in project JGroups by belaban.
the class DISCARD method down.
public Object down(Event evt) {
switch(evt.getType()) {
case Event.VIEW_CHANGE:
View view = evt.getArg();
List<Address> mbrs = view.getMembers();
members.clear();
members.addAll(mbrs);
if (discard_dialog != null)
discard_dialog.handleView(mbrs);
break;
case Event.GET_PING_DATA:
if (discard_all)
return null;
break;
}
return down_prot.down(evt);
}
Aggregations