public synchronized RspList<Object> getResponseList() throws Exception { while (expectedResponses > 0 && retval == null) { try { this.wait(timeout); } catch (InterruptedException e) { // reset interruption flag Thread.currentThread().interrupt(); expectedResponses = -1; } } // Now we either have the response we need or aren't expecting any more responses - or have // run out of time. if (retval != null) return retval; else if (exception != null) throw exception; else if (expectedResponses == 0) throw new RpcException( format( "No more valid responses. Received invalid responses from all of %s", futures.values())); else throw new TimeoutException( format( "Timed out waiting for %s for valid responses from any of %s.", Util.prettyPrintTime(timeout), futures.values())); }
@Override @SuppressWarnings("unchecked") public synchronized void futureDone(Future<Object> objectFuture) { SenderContainer sc = futures.get(objectFuture); if (sc.processed) { // This can happen - it is a race condition in JGroups' NotifyingFuture.setListener() where // a listener // could be notified twice. if (trace) log.tracef( "Not processing callback; already processed callback for sender %s", sc.address); } else { sc.processed = true; Address sender = sc.address; boolean done = false; try { if (retval == null) { Object response = objectFuture.get(); if (trace) log.tracef("Received response: %s from %s", response, sender); filter.isAcceptable(response, sender); if (!filter.needMoreResponses()) { retval = new RspList(Collections.singleton(new Rsp(sender, response))); done = true; // TODO cancel other tasks? } } else { if (trace) log.tracef( "Skipping response from %s since a valid response for this request has already been received", sender); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } catch (ExecutionException e) { exception = e; if (e.getCause() instanceof org.jgroups.TimeoutException) exception = new TimeoutException("Timeout!", e); else if (e.getCause() instanceof Exception) exception = (Exception) e.getCause(); else exception = new CacheException("Caught a throwable", e.getCause()); if (log.isDebugEnabled()) log.debugf( "Caught exception %s from sender %s. Will skip this response.", exception.getClass().getName(), sender); log.trace("Exception caught: ", exception); } finally { expectedResponses--; if (expectedResponses == 0 || done) { this.notify(); // make sure to awake waiting thread, but avoid unnecessary wakeups! } } } }