/** * Invoked upon receiving a MERGE event from the MERGE layer. Starts the merge protocol. * See description of protocol in DESIGN. * @param views A List of <em>different</em> views detected by the merge protocol */ public void merge(Map<Address, View> views) { merger.merge(views); }
/** * Get the view and digest and send back both (MergeData) in the form of a MERGE_RSP to the sender. * If a merge is already in progress, send back a MergeData with the merge_rejected field set to true. * @param sender The address of the merge leader * @param merge_id The merge ID * @param mbrs The set of members from which we expect responses. Guaranteed to be non-null */ public void handleMergeRequest(Address sender, MergeId merge_id, Collection<? extends Address> mbrs) { try { _handleMergeRequest(sender, merge_id, mbrs); } catch(Throwable t) { log.error("%s: failure handling the merge request: %s", gms.local_addr, t.getMessage()); cancelMerge(merge_id); sendMergeRejectedResponse(sender, merge_id); } }
/** * @param views Guaranteed to be non-null and to have >= 2 members, or else this thread would not be started */ public synchronized void start(Map<Address, View> views) { if(thread != null && thread.isAlive()) // the merge thread is already running return; this.coords.clear(); this.subviews.clear(); subviews.addAll(views.values()); // now remove all members which don't have us in their view, so RPCs won't block (e.g. FLUSH) // https://jira.jboss.org/browse/JGRP-1061 sanitizeViews(views); Map<Address,Collection<Address>> tmp_coords=determineMergeCoords(views); this.coords.putAll(tmp_coords); thread=gms.getThreadFactory().newThread(this, "MergeTask"); thread.setDaemon(true); thread.start(); }
protected void _handleMergeRequest(Address sender, MergeId merge_id, Collection<? extends Address> mbrs) throws Exception { MergeId current_merge_id=this.merge_id; boolean success=matchMergeId(merge_id) || setMergeId(null, merge_id); if(!success) { log.trace("%s: merge %s is already in progress, received merge-id=%s", gms.local_addr, current_merge_id, merge_id); Digest digest=fetchDigestsFromAllMembersInSubPartition(view, merge_id); if(digest == null || digest.capacity() == 0) throw new Exception("failed fetching digests from subpartition members; dropping merge response"); sendMergeResponse(sender, view, digest, merge_id);
protected synchronized void forceCancelMerge() { if(this.merge_id != null) cancelMerge(this.merge_id); }
public void run() { // 1. Generate merge_id final MergeId new_merge_id=MergeId.create(gms.local_addr); final Collection<Address> coordsCopy=new ArrayList<>(coords.keySet()); long start=System.currentTimeMillis(); try { _run(new_merge_id, coordsCopy); // might remove members from coordsCopy } catch(Throwable ex) { if(ex instanceof Error || ex instanceof RuntimeException) log.warn(gms.local_addr + ": merge is cancelled", ex); else log.warn("%s: merge is cancelled: %s", gms.local_addr, ex.getMessage()); sendMergeCancelledMessage(coordsCopy, new_merge_id); cancelMerge(new_merge_id); // the message above cancels the merge, too, but this is a 2nd line of defense } finally { /* 5. if flush is in stack stop the flush for entire cluster [JGRP-700] - FLUSH: flushing should span merge */ if(gms.flushProtocolInStack) gms.stopFlush(); thread=null; } long diff=System.currentTimeMillis() - start; log.debug("%s: merge %s took %d ms", gms.local_addr, new_merge_id, diff); }
/** * 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); } }
/** * Invoked upon receiving a MERGE event from the MERGE layer. Starts the merge protocol. * See description of protocol in DESIGN. * @param views A List of <em>different</em> views detected by the merge protocol, keyed by sender */ public void merge(Map<Address, View> views) { if(views == null || views.isEmpty()) { log.warn("the views passed with the MERGE event were empty (or null); ignoring MERGE event"); return; } if(View.sameViews(views.values())) { log.debug("MERGE event is ignored because of identical views: %s", Util.printListWithDelimiter(views.values(), ", ")); return; } if(isMergeInProgress()) { log.trace("%s: merge is already running (merge_id=%s)", gms.local_addr, merge_id); return; } Address merge_leader=determineMergeLeader(views); if(merge_leader == null) return; if(merge_leader.equals(gms.local_addr)) { log.debug("%s: I will be the merge leader. Starting the merge task. Views: %s", gms.local_addr, views); merge_task.start(views); } else log.trace("%s: I'm not the merge leader, waiting for merge leader (%s) to start merge", gms.local_addr, merge_leader); }
@ManagedOperation(description="Forces cancellation of current merge task") public void cancelMerge() { merger.forceCancelMerge(); }
/** * Fetches the digests from all members and installs them again. Used only for diagnosis and support; don't * use this otherwise ! */ void fixDigests() { merger.fixDigests(); }
/** * 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 MergeId getMergeId() { return merger.getMergeId(); }
public void init() throws Exception { merger=new Merger(this); if(view_ack_collection_timeout <= 0) throw new IllegalArgumentException("view_ack_collection_timeout has to be greater than 0"); if(merge_timeout <= 0) throw new IllegalArgumentException("merge_timeout has to be greater than 0"); prev_members=new BoundedList<>(num_prev_mbrs); prev_views=new BoundedList<>(num_prev_views); TP transport=getTransport(); timer=transport.getTimer(); if(timer == null) throw new Exception("timer is null"); if(impl != null) impl.init(); transport.registerProbeHandler(this); }
protected void _handleMergeRequest(Address sender, MergeId merge_id, Collection<? extends Address> mbrs) throws Exception { MergeId current_merge_id=this.merge_id; boolean success=matchMergeId(merge_id) || setMergeId(null, merge_id); if(!success) { log.trace("%s: merge %s is already in progress, received merge-id=%s", gms.local_addr, current_merge_id, merge_id); Digest digest=fetchDigestsFromAllMembersInSubPartition(view, merge_id); if(digest == null || digest.capacity() == 0) throw new Exception("failed fetching digests from subpartition members; dropping merge response"); sendMergeResponse(sender, view, digest, merge_id);
public void run() { cancelMerge(my_merge_id); }
public void run() { // 1. Generate merge_id final MergeId new_merge_id=MergeId.create(gms.local_addr); final Collection<Address> coordsCopy=new ArrayList<>(coords.keySet()); long start=System.currentTimeMillis(); try { _run(new_merge_id, coordsCopy); // might remove members from coordsCopy } catch(Throwable ex) { if(ex instanceof Error || ex instanceof RuntimeException) log.warn(gms.local_addr + ": merge is cancelled", ex); else log.warn("%s: merge is cancelled: %s", gms.local_addr, ex.getMessage()); sendMergeCancelledMessage(coordsCopy, new_merge_id); cancelMerge(new_merge_id); // the message above cancels the merge, too, but this is a 2nd line of defense } finally { /* 5. if flush is in stack stop the flush for entire cluster [JGRP-700] - FLUSH: flushing should span merge */ if(gms.flushProtocolInStack) gms.stopFlush(); thread=null; } long diff=System.currentTimeMillis() - start; log.debug("%s: merge %s took %d ms", gms.local_addr, new_merge_id, diff); }
/** * 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); } }
/** * Invoked upon receiving a MERGE event from the MERGE layer. Starts the merge protocol. * See description of protocol in DESIGN. * @param views A List of <em>different</em> views detected by the merge protocol, keyed by sender */ public void merge(Map<Address, View> views) { if(views == null || views.isEmpty()) { log.warn("the views passed with the MERGE event were empty (or null); ignoring MERGE event"); return; } if(View.sameViews(views.values())) { log.debug("MERGE event is ignored because of identical views: %s", Util.printListWithDelimiter(views.values(), ", ")); return; } if(isMergeInProgress()) { log.trace("%s: merge is already running (merge_id=%s)", gms.local_addr, merge_id); return; } Address merge_leader=determineMergeLeader(views); if(merge_leader == null) return; if(merge_leader.equals(gms.local_addr)) { log.debug("%s: I will be the merge leader. Starting the merge task. Views: %s", gms.local_addr, views); merge_task.start(views); } else log.trace("%s: I'm not the merge leader, waiting for merge leader (%s) to start merge", gms.local_addr, merge_leader); }
merger.forceCancelMerge();
/** * Fetches the digests from all members and installs them again. Used only for diagnosis and support; don't * use this otherwise ! */ void fixDigests() { merger.fixDigests(); }