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); } }
@ManagedOperation public String dumpViewHandlerHistory() { return view_handler.dumpHistory(); }
/** We're guaranteed that only one thread will be called with this method at any time */ protected void process(Collection<R> requests) { for(;;) { while(!requests.isEmpty()) { removeAndProcess(requests); // remove matching requests and process them } lock.lock(); try { if(requests.isEmpty()) { setProcessing(false); return; } } finally { lock.unlock(); } } }
protected boolean _add(R req) { if(req == null || suspended.get()) { log().trace("%s: queue is suspended; request %s is discarded", gms.getLocalAddress(), req); return false; } String log=new Date() + ": " + req.toString(); count.incrementAndGet(); lock.lock(); try { if(!requests.contains(req)) { requests.add(req); history.add(log); } return count.decrementAndGet() == 0 && !processing && setProcessing(true); } finally { lock.unlock(); } }
/** 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(); }
@ManagedOperation public void resumeViewHandler() {view_handler.resume();}
@ManagedOperation public String dumpViewHandlerQueue() { return view_handler.dumpQueue(); } @ManagedOperation
@ManagedAttribute public int getViewHandlerSize() {return view_handler.size();} @ManagedAttribute
/** * Removes requests as long as they match - breaks at the first non-matching request or when requests is empty * This method must catch all exceptions; or else process() might return without setting processing to true again! */ protected void removeAndProcess(Collection<R> requests) { try { Collection<R> removed=new ArrayList<>(); Iterator<R> it=requests.iterator(); R first_req=it.next(); removed.add(first_req); it.remove(); while(it.hasNext()) { R next=it.next(); if(req_matcher.test(first_req, next)) { removed.add(next); it.remove(); } else break; } req_processor.accept(removed); } catch(Throwable t) { log().error("failed processing requests", t); } }
protected boolean _add(Collection<R> reqs) { if(reqs == null || reqs.isEmpty() || suspended.get()) { log().trace("%s: queue is suspended; requests are discarded", gms.getLocalAddress()); return false; } count.incrementAndGet(); lock.lock(); try { for(R req: reqs) { if(!requests.contains(req)) { requests.add(req); history.add(new Date() + ": " + req.toString()); } } return count.decrementAndGet() == 0 && !processing && setProcessing(true); } finally { lock.unlock(); } }
/** 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(); }
/** We're guaranteed that only one thread will be called with this method at any time */ protected void process(Collection<R> requests) { for(;;) { while(!requests.isEmpty()) { removeAndProcess(requests); // remove matching requests and process them } lock.lock(); try { if(requests.isEmpty()) { setProcessing(false); return; } } finally { lock.unlock(); } } }
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)); } }
@ManagedOperation public String dumpViewHandlerQueue() { return view_handler.dumpQueue(); } @ManagedOperation
@ManagedAttribute public int getViewHandlerSize() {return view_handler.size();} @ManagedAttribute
/** * Removes requests as long as they match - breaks at the first non-matching request or when requests is empty * This method must catch all exceptions; or else process() might return without setting processing to true again! */ protected void removeAndProcess(Collection<R> requests) { try { Collection<R> removed=new ArrayList<>(); Iterator<R> it=requests.iterator(); R first_req=it.next(); removed.add(first_req); it.remove(); while(it.hasNext()) { R next=it.next(); if(req_matcher.test(first_req, next)) { removed.add(next); it.remove(); } else break; } req_processor.accept(removed); } catch(Throwable t) { log().error("failed processing requests", t); } }
@SuppressWarnings("unchecked") protected boolean _add(R ... reqs) { if(reqs == null || reqs.length == 0 || suspended.get()) { log().trace("%s: queue is suspended; requests are discarded", gms.getLocalAddress()); return false; } count.incrementAndGet(); lock.lock(); try { for(R req: reqs) { if(!requests.contains(req)) { requests.add(req); history.add(new Date() + ": " + req.toString()); } } return count.decrementAndGet() == 0 && !processing && setProcessing(true); } finally { lock.unlock(); } }
public Object up(Event evt) { switch(evt.getType()) { case Event.SUSPECT: Object retval=up_prot.up(evt); // todo: change this to only accept lists in 4.1 Collection<Address> suspects=evt.arg() instanceof Address? Collections.singletonList(evt.arg()) : evt.arg(); Request[] suspect_reqs=new Request[suspects.size()]; int index=0; for(Address mbr: suspects) suspect_reqs[index++]=new Request(Request.SUSPECT, mbr); view_handler.add(suspect_reqs); ack_collector.suspect(suspects); merge_ack_collector.suspect(suspects); return retval; case Event.UNSUSPECT: impl.unsuspect(evt.getArg()); return null; // discard case Event.MERGE: view_handler.add(new Request(Request.MERGE, null, evt.getArg())); return null; // don't pass up case Event.IS_MERGE_IN_PROGRESS: return merger.isMergeInProgress(); } return up_prot.up(evt); }