Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

JGRP-1007 - Flush: change signature of JChannel#startFlush

  • Loading branch information...
commit c1c1251f5c52164e4b2a470272a755cf29775e8e 1 parent 6eade6a
vblagoje vblagoje authored
51 src/org/jgroups/Channel.java
@@ -327,37 +327,34 @@ public Receiver getReceiver() {
327 327 abstract public boolean flushSupported();
328 328
329 329 /**
330   - * Performs a partial flush in a cluster for flush participants.<p/>
331   - * All pending messages are flushed out only for the flush participants. The remaining members in a cluster are not
332   - * included in the flush. The flush participants should be a proper subset of a current view.<p/>
333   - * @param automatic_resume Call {@link #stopFlush()} after the flush
334   - * @return true if FLUSH completed within the timeout
335   - * @see #startFlush(boolean)
336   - */
337   - abstract public boolean startFlush(List<Address> flushParticipants,boolean automatic_resume);
338   -
339   - /**
340   - * Will perform a flush of the system, ie. all pending messages are flushed out of the system and all members
341   - * ack their reception. After this call returns, no member will be sending any messages until
342   - * {@link #stopFlush()} is called.<p/>
343   - * In case of flush collisions, a random sleep time backoff algorithm is employed and the flush is reattempted for
344   - * numberOfAttempts. Therefore this method is guaranteed to return after timeout x numberOfAttempts miliseconds.
345   - * @param automatic_resume Call {@link #stopFlush()} after the flush
346   - * @return true if FLUSH completed within the timeout
  330 + * Performs a partial flush in a cluster for flush participants.
  331 + * <p/>
  332 + * All pending messages are flushed out only for the flush participants. The remaining members
  333 + * in a cluster are not included in the flush. The flush participants should be a proper subset
  334 + * of a current view.
  335 + * <p/>
  336 + *
  337 + * @param automatic_resume
  338 + * Call {@link #stopFlush()} after the flush
  339 + * @see #startFlush(boolean)
347 340 */
348   - abstract public boolean startFlush(boolean automatic_resume);
  341 + abstract public void startFlush(List<Address> flushParticipants, boolean automatic_resume)
  342 + throws Exception;
349 343
350 344 /**
351   - * Will perform a flush of the system, ie. all pending messages are flushed out of the
352   - * system and all members ack their reception. After this call returns, no member will
353   - * be sending any messages until {@link #stopFlush()} is called.
354   - * @param timeout
355   - * @param automatic_resume Call {@link #stopFlush()} after the flush
356   - * @return true if FLUSH completed within the timeout
357   - * @see #startFlush(boolean)
  345 + * Will perform a flush of the system, ie. all pending messages are flushed out of the system
  346 + * and all members ack their reception. After this call returns, no member will be sending any
  347 + * messages until {@link #stopFlush()} is called.
  348 + * <p/>
  349 + * In case of flush collisions, a random sleep time backoff algorithm is employed and the flush
  350 + * is reattempted for numberOfAttempts. Therefore this method is guaranteed to return after
  351 + * timeout x numberOfAttempts miliseconds.
  352 + *
  353 + * @param automatic_resume
  354 + * Call {@link #stopFlush()} after the flush
358 355 */
359   - abstract public boolean startFlush(long timeout, boolean automatic_resume);
360   -
  356 + abstract public void startFlush(boolean automatic_resume) throws Exception;
  357 +
361 358 abstract public void stopFlush();
362 359
363 360 abstract public void stopFlush(List<Address> flushParticipants);
75 src/org/jgroups/JChannel.java
@@ -1014,55 +1014,56 @@ public boolean flushSupported() {
1014 1014 }
1015 1015
1016 1016 /** {@inheritDoc} */
1017   - public boolean startFlush(boolean automatic_resume) {
1018   - if(!flushSupported()) {
1019   - throw new IllegalStateException("Flush is not supported, add pbcast.FLUSH protocol to your configuration");
1020   - }
1021   - boolean successfulFlush=(Boolean)down(new Event(Event.SUSPEND));
1022   -
1023   - if(automatic_resume)
1024   - stopFlush();
1025   -
1026   - return successfulFlush;
  1017 + public void startFlush(boolean automatic_resume) throws Exception {
  1018 + if (!flushSupported()) {
  1019 + throw new IllegalStateException(
  1020 + "Flush is not supported, add pbcast.FLUSH protocol to your configuration");
  1021 + }
  1022 + try {
  1023 + down(new Event(Event.SUSPEND));
  1024 + } catch (Exception e) {
  1025 + throw new ChannelException("Flush failed", e.getCause());
  1026 + } finally {
  1027 + if (automatic_resume)
  1028 + stopFlush();
  1029 + }
1027 1030 }
1028 1031
1029 1032 /** {@inheritDoc} */
1030   - public boolean startFlush(List<Address> flushParticipants,boolean automatic_resume) {
1031   - boolean successfulFlush;
1032   - if(!flushSupported()){
1033   - throw new IllegalStateException("Flush is not supported, add pbcast.FLUSH protocol to your configuration");
  1033 + public void startFlush(List<Address> flushParticipants, boolean automatic_resume)
  1034 + throws Exception {
  1035 + if (!flushSupported()) {
  1036 + throw new IllegalStateException(
  1037 + "Flush is not supported, add pbcast.FLUSH protocol to your configuration");
1034 1038 }
1035 1039 View v = getView();
1036   - if(v != null && v.getMembers().containsAll(flushParticipants)){
1037   - successfulFlush=(Boolean)down(new Event(Event.SUSPEND, flushParticipants));
1038   - }else{
  1040 + boolean validParticipants = v != null && v.getMembers().containsAll(flushParticipants);
  1041 + if (!validParticipants)
1039 1042 throw new IllegalArgumentException("Current view " + v
1040   - + " does not contain all flush participants "
1041   - + flushParticipants);
1042   - }
1043   -
1044   - if(automatic_resume)
1045   - stopFlush(flushParticipants);
1046   -
1047   - return successfulFlush;
1048   - }
1049   -
1050   - /** {@inheritDoc} */
1051   - public boolean startFlush(long timeout, boolean automatic_resume) {
1052   - return startFlush(automatic_resume);
  1043 + + " does not contain all flush participants " + flushParticipants);
  1044 + try {
  1045 + down(new Event(Event.SUSPEND, flushParticipants));
  1046 + } catch (Exception e) {
  1047 + throw new ChannelException("Flush failed", e.getCause());
  1048 + } finally {
  1049 + if (automatic_resume)
  1050 + stopFlush(flushParticipants);
  1051 + }
1053 1052 }
1054 1053
1055 1054 public void stopFlush() {
1056   - if(!flushSupported()) {
1057   - throw new IllegalStateException("Flush is not supported, add pbcast.FLUSH protocol to your configuration");
1058   - }
1059   - down(new Event(Event.RESUME));
  1055 + if (!flushSupported()) {
  1056 + throw new IllegalStateException(
  1057 + "Flush is not supported, add pbcast.FLUSH protocol to your configuration");
  1058 + }
  1059 + down(new Event(Event.RESUME));
1060 1060 }
1061 1061
1062 1062 public void stopFlush(List<Address> flushParticipants) {
1063   - if(!flushSupported()) {
1064   - throw new IllegalStateException("Flush is not supported, add pbcast.FLUSH protocol to your configuration");
1065   - }
  1063 + if (!flushSupported()) {
  1064 + throw new IllegalStateException(
  1065 + "Flush is not supported, add pbcast.FLUSH protocol to your configuration");
  1066 + }
1066 1067 down(new Event(Event.RESUME, flushParticipants));
1067 1068 }
1068 1069
74 src/org/jgroups/protocols/pbcast/FLUSH.java
@@ -41,6 +41,8 @@
41 41 @MBean(description = "Flushes the cluster")
42 42 public class FLUSH extends Protocol {
43 43
  44 + private static final FlushStartResult SUCCESS_START_FLUSH = new FlushStartResult(Boolean.TRUE,null);
  45 +
44 46 /*
45 47 * ------------------------------------------ Properties------------------------------------------
46 48 */
@@ -120,7 +122,7 @@
120 122 @GuardedBy("sharedLock")
121 123 private boolean flushCompleted = false;
122 124
123   - private final Promise<Boolean> flush_promise = new Promise<Boolean>();
  125 + private final Promise<FlushStartResult> flush_promise = new Promise<FlushStartResult>();
124 126
125 127 private final Promise<Boolean> flush_unblock_promise = new Promise<Boolean>();
126 128
@@ -194,18 +196,17 @@ public int getNumberOfFlushes() {
194 196 }
195 197
196 198 @ManagedOperation(description = "Request cluster flush")
197   - public boolean startFlush() {
198   - return startFlush(new Event(Event.SUSPEND));
  199 + public void startFlush() {
  200 + startFlush(new Event(Event.SUSPEND));
199 201 }
200 202
201 203 @SuppressWarnings("unchecked")
202   - private boolean startFlush(Event evt) {
  204 + private void startFlush(Event evt) {
203 205 List<Address> flushParticipants = (List<Address>) evt.getArg();
204   - return startFlush(flushParticipants);
  206 + startFlush(flushParticipants);
205 207 }
206 208
207   - private boolean startFlush(List<Address> flushParticipants) {
208   - boolean successfulFlush = false;
  209 + private void startFlush(List<Address> flushParticipants) throws RuntimeException {
209 210 if (!flushInProgress.get()) {
210 211 flush_promise.reset();
211 212 synchronized(sharedLock) {
@@ -214,19 +215,21 @@ private boolean startFlush(List<Address> flushParticipants) {
214 215 }
215 216 onSuspend(flushParticipants);
216 217 try {
217   - Boolean r = flush_promise.getResultWithTimeout(start_flush_timeout);
218   - successfulFlush = r.booleanValue();
  218 + FlushStartResult r = flush_promise.getResultWithTimeout(start_flush_timeout);
  219 + if(r.failed())
  220 + throw new RuntimeException(r.getFailureCause());
219 221 } catch (TimeoutException e) {
220   - if (log.isDebugEnabled())
221   - log.debug(localAddress
222   - + ": timed out waiting for flush responses after "
223   - + start_flush_timeout
224   - + " ms. Rejecting flush to participants "
225   - + flushParticipants);
226 222 rejectFlush(flushParticipants, currentViewId());
  223 + throw new RuntimeException(localAddress
  224 + + " timed out waiting for flush responses after "
  225 + + start_flush_timeout
  226 + + " ms. Rejected flush to participants "
  227 + + flushParticipants,e);
227 228 }
228 229 }
229   - return successfulFlush;
  230 + else {
  231 + throw new RuntimeException("Flush attempt is in progress");
  232 + }
230 233 }
231 234
232 235 @ManagedOperation(description = "Request end of flush in a cluster")
@@ -265,7 +268,8 @@ public Object down(Event evt) {
265 268 return handleConnect(evt, false);
266 269
267 270 case Event.SUSPEND:
268   - return startFlush(evt);
  271 + startFlush(evt);
  272 + break;
269 273
270 274
271 275 // only for testing, see FLUSH#testFlushWithCrashedFlushCoordinator
@@ -320,7 +324,7 @@ private void blockMessageDuringFlush() {
320 324 if (shouldSuspendByItself) {
321 325 isBlockingFlushDown = false;
322 326 log.warn(localAddress + ": unblocking after " + timeout + "ms");
323   - flush_promise.setResult(Boolean.TRUE);
  327 + flush_promise.setResult(new FlushStartResult(Boolean.TRUE,null));
324 328 notBlockedDown.signalAll();
325 329 }
326 330 } catch (InterruptedException e) {
@@ -408,7 +412,7 @@ public void run() {
408 412 new Thread(r).start();
409 413 }
410 414 // however, flush should fail/retry as soon as one FAIL is received
411   - flush_promise.setResult(Boolean.FALSE);
  415 + flush_promise.setResult(new FlushStartResult(Boolean.FALSE, new Exception("Flush failed for " + msg.getSrc())));
412 416 break;
413 417
414 418 case FlushHeader.FLUSH_COMPLETED:
@@ -461,7 +465,8 @@ public void run() {
461 465 break;
462 466
463 467 case Event.SUSPEND:
464   - return startFlush(evt);
  468 + startFlush(evt);
  469 + break;
465 470
466 471 case Event.RESUME:
467 472 onResume(evt);
@@ -492,7 +497,7 @@ private void onFlushReconcileOK(Message msg) {
492 497 synchronized (sharedLock) {
493 498 reconcileOks.add(msg.getSrc());
494 499 if (reconcileOks.size() >= flushMembers.size()) {
495   - flush_promise.setResult(Boolean.TRUE);
  500 + flush_promise.setResult(SUCCESS_START_FLUSH);
496 501 if (log.isDebugEnabled())
497 502 log.debug(localAddress + ": all FLUSH_RECONCILE_OK received");
498 503 }
@@ -660,7 +665,7 @@ private void onSuspend(final List<Address> members) {
660 665 participantsInFlush));
661 666 }
662 667 if (participantsInFlush.isEmpty()) {
663   - flush_promise.setResult(Boolean.TRUE);
  668 + flush_promise.setResult(SUCCESS_START_FLUSH);
664 669 } else {
665 670 down_prot.down(new Event(Event.MSG, msg));
666 671 if (log.isDebugEnabled())
@@ -792,7 +797,7 @@ private void onFlushCompleted(Address address, final FlushHeader header) {
792 797 if (needsReconciliationPhase) {
793 798 down_prot.down(new Event(Event.MSG, msg));
794 799 } else if (flushCompleted) {
795   - flush_promise.setResult(Boolean.TRUE);
  800 + flush_promise.setResult(SUCCESS_START_FLUSH);
796 801 if (log.isDebugEnabled())
797 802 log.debug(localAddress + ": all FLUSH_COMPLETED received");
798 803 } else if (collision) {
@@ -885,6 +890,29 @@ private void onSuspect(Address address) {
885 890 log.debug(localAddress + ": sent FLUSH_COMPLETED message to " + flushCoordinator);
886 891 }
887 892 }
  893 +
  894 + private static class FlushStartResult {
  895 + private final Boolean result;
  896 + private final Exception failureCause;
  897 +
  898 +
  899 + public FlushStartResult(Boolean result, Exception failureCause) {
  900 + this.result = result;
  901 + this.failureCause = failureCause;
  902 + }
  903 +
  904 + public Boolean getResult() {
  905 + return result;
  906 + }
  907 +
  908 + public boolean failed(){
  909 + return result == Boolean.FALSE;
  910 + }
  911 +
  912 + public Exception getFailureCause() {
  913 + return failureCause;
  914 + }
  915 + }
888 916
889 917 public static class FlushHeader extends Header {
890 918 public static final byte START_FLUSH = 0;
15 src/org/jgroups/protocols/pbcast/GMS.java
@@ -693,17 +693,20 @@ protected boolean _startFlush(final View new_view, int maxAttempts, long randomF
693 693 }
694 694
695 695 try {
696   - boolean successfulFlush=true;
  696 + boolean successfulFlush=false;
697 697 boolean validView=new_view != null && new_view.size() > 0;
698 698 if(validView && flushProtocolInStack) {
699 699
700 700 int attemptCount = 0;
701   - while(attemptCount < maxAttempts){
702   - successfulFlush=(Boolean)up_prot.up(new Event(Event.SUSPEND, new ArrayList<Address>(new_view.getMembers())));
703   - if(successfulFlush)
  701 + while (attemptCount < maxAttempts) {
  702 + try {
  703 + up_prot.up(new Event(Event.SUSPEND, new ArrayList<Address>(new_view.getMembers())));
  704 + successfulFlush = true;
704 705 break;
705   - Util.sleepRandom(randomFloor,randomCeiling);
706   - attemptCount++;
  706 + } catch (Exception e) {
  707 + Util.sleepRandom(randomFloor, randomCeiling);
  708 + attemptCount++;
  709 + }
707 710 }
708 711
709 712 if(successfulFlush) {
39 src/org/jgroups/util/Util.java
@@ -2859,17 +2859,19 @@ public static String shortName(String hostname) {
2859 2859 return hostname;
2860 2860 }
2861 2861
2862   - public static boolean startFlush(Channel c, List<Address> flushParticipants, int numberOfAttempts, long randomSleepTimeoutFloor,long randomSleepTimeoutCeiling) {
2863   - boolean successfulFlush = false;
2864   - int attemptCount = 0;
2865   - while(attemptCount < numberOfAttempts){
2866   - successfulFlush = c.startFlush(flushParticipants, false);
2867   - if(successfulFlush)
2868   - break;
2869   - Util.sleepRandom(randomSleepTimeoutFloor,randomSleepTimeoutCeiling);
2870   - attemptCount++;
2871   - }
2872   - return successfulFlush;
  2862 + public static boolean startFlush(Channel c, List<Address> flushParticipants,
  2863 + int numberOfAttempts, long randomSleepTimeoutFloor, long randomSleepTimeoutCeiling) {
  2864 + int attemptCount = 0;
  2865 + while (attemptCount < numberOfAttempts) {
  2866 + try {
  2867 + c.startFlush(flushParticipants, false);
  2868 + return true;
  2869 + } catch (Exception e) {
  2870 + Util.sleepRandom(randomSleepTimeoutFloor, randomSleepTimeoutCeiling);
  2871 + attemptCount++;
  2872 + }
  2873 + }
  2874 + return false;
2873 2875 }
2874 2876
2875 2877 public static boolean startFlush(Channel c, List<Address> flushParticipants) {
@@ -2877,16 +2879,17 @@ public static boolean startFlush(Channel c, List<Address> flushParticipants) {
2877 2879 }
2878 2880
2879 2881 public static boolean startFlush(Channel c, int numberOfAttempts, long randomSleepTimeoutFloor,long randomSleepTimeoutCeiling) {
2880   - boolean successfulFlush = false;
2881 2882 int attemptCount = 0;
2882 2883 while(attemptCount < numberOfAttempts){
2883   - successfulFlush = c.startFlush(false);
2884   - if(successfulFlush)
2885   - break;
2886   - Util.sleepRandom(randomSleepTimeoutFloor,randomSleepTimeoutCeiling);
2887   - attemptCount++;
  2884 + try{
  2885 + c.startFlush(false);
  2886 + return true;
  2887 + } catch(Exception e) {
  2888 + Util.sleepRandom(randomSleepTimeoutFloor,randomSleepTimeoutCeiling);
  2889 + attemptCount++;
  2890 + }
2888 2891 }
2889   - return successfulFlush;
  2892 + return false;
2890 2893 }
2891 2894
2892 2895 public static boolean startFlush(Channel c) {
4 tests/junit/org/jgroups/tests/FlushTest.java
@@ -130,11 +130,9 @@ public void testSequentialFlushInvocation() throws Exception {
130 130 for (int i = 0; i < 100; i++) {
131 131 System.out.print("flush #" + i + ": ");
132 132 long start = System.currentTimeMillis();
133   - boolean status = channel.startFlush(false);
  133 + channel.startFlush(false);
134 134 channel.stopFlush();
135 135 long diff = System.currentTimeMillis() - start;
136   - System.out.println(status ? " OK (in " + diff + " ms)" : " FAIL");
137   - assert status;
138 136 }
139 137 } finally {
140 138 Util.close(channel, channel2, channel3);

0 comments on commit c1c1251

Please sign in to comment.
Something went wrong with that request. Please try again.