private static RspList<Object> processCalls( ReplicableCommand command, boolean broadcast, long timeout, RspFilter filter, List<Address> dests, ResponseMode mode, Marshaller marshaller, CommandAwareRpcDispatcher card, boolean oob, boolean anycasting) throws Exception { if (trace) log.tracef("Replication task sending %s to addresses %s", command, dests); /// HACK ALERT! Used for ISPN-1789. Enable RSVP if the command is a cache view control // command. boolean rsvp = command instanceof CacheViewControlCommand; RspList<Object> retval = null; Buffer buf; if (broadcast || FORCE_MCAST) { buf = marshallCall(marshaller, command); retval = card.castMessage( dests, constructMessage(buf, null, oob, mode, rsvp), new RequestOptions(mode, timeout, false, filter)); } else { RequestOptions opts = new RequestOptions(mode, timeout); if (dests.isEmpty()) return new RspList<Object>(); buf = marshallCall(marshaller, command); // if at all possible, try not to use JGroups' ANYCAST for now. Multiple (parallel) UNICASTs // are much faster. if (filter != null) { // This is possibly a remote GET. // These UNICASTs happen in parallel using sendMessageWithFuture. Each future has a // listener attached // (see FutureCollator) and the first successful response is used. FutureCollator futureCollator = new FutureCollator(filter, dests.size(), timeout); for (Address a : dests) { NotifyingFuture<Object> f = card.sendMessageWithFuture(constructMessage(buf, a, oob, mode, rsvp), opts); futureCollator.watchFuture(f, a); } retval = futureCollator.getResponseList(); } else if (mode == ResponseMode.GET_ALL) { // A SYNC call that needs to go everywhere Map<Address, Future<Object>> futures = new HashMap<Address, Future<Object>>(dests.size()); for (Address dest : dests) futures.put( dest, card.sendMessageWithFuture(constructMessage(buf, dest, oob, mode, rsvp), opts)); retval = new RspList<Object>(); // a get() on each future will block till that call completes. for (Map.Entry<Address, Future<Object>> entry : futures.entrySet()) { try { retval.addRsp(entry.getKey(), entry.getValue().get(timeout, MILLISECONDS)); } catch (java.util.concurrent.TimeoutException te) { throw new TimeoutException( formatString( "Timed out after %s waiting for a response from %s", prettyPrintTime(timeout), entry.getKey())); } } } else if (mode == ResponseMode.GET_NONE) { // An ASYNC call. We don't care about responses. for (Address dest : dests) card.sendMessage(constructMessage(buf, dest, oob, mode, rsvp), opts); } } // we only bother parsing responses if we are not in ASYNC mode. if (mode != ResponseMode.GET_NONE) { if (trace) log.tracef("Responses: %s", retval); // a null response is 99% likely to be due to a marshalling problem - we throw a NSE, this // needs to be changed when // JGroups supports http://jira.jboss.com/jira/browse/JGRP-193 // the serialization problem could be on the remote end and this is why we cannot catch this // above, when marshalling. if (retval == null) throw new NotSerializableException( "RpcDispatcher returned a null. This is most often caused by args for " + command.getClass().getSimpleName() + " not being serializable."); } return retval; }
private static RspList<Object> processCalls( ReplicableCommand command, boolean broadcast, long timeout, RspFilter filter, List<Address> dests, ResponseMode mode, DeliverOrder deliverOrder, Marshaller marshaller, CommandAwareRpcDispatcher card, boolean ignoreLeavers) throws Exception { if (trace) log.tracef( "Replication task sending %s to addresses %s with response mode %s", command, dests, mode); boolean rsvp = isRsvpCommand(command); RspList<Object> retval = null; Buffer buf; if (deliverOrder == DeliverOrder.TOTAL) { buf = marshallCall(marshaller, command); Message message = constructMessage(buf, new AnycastAddress(dests), mode, rsvp, deliverOrder); retval = card.castMessage(dests, message, new RequestOptions(mode, timeout, false, filter)); } else if (broadcast || FORCE_MCAST) { buf = marshallCall(marshaller, command); RequestOptions opts = new RequestOptions(mode, timeout, false, filter); // Only the commands in total order must be received... // For correctness, ispn doesn't need their own message, so add own address to exclusion list opts.setExclusionList(card.getChannel().getAddress()); retval = card.castMessage(dests, constructMessage(buf, null, mode, rsvp, deliverOrder), opts); } else { RequestOptions opts = new RequestOptions(mode, timeout); // Only the commands in total order must be received... opts.setExclusionList(card.getChannel().getAddress()); if (dests.isEmpty()) return new RspList<>(); buf = marshallCall(marshaller, command); // if at all possible, try not to use JGroups' ANYCAST for now. Multiple (parallel) UNICASTs // are much faster. if (filter != null) { // This is possibly a remote GET. // These UNICASTs happen in parallel using sendMessageWithFuture. Each future has a // listener attached // (see FutureCollator) and the first successful response is used. FutureCollator futureCollator = new FutureCollator(filter, dests.size(), timeout, card.timeService); for (Address a : dests) { NotifyingFuture<Object> f = card.sendMessageWithFuture(constructMessage(buf, a, mode, rsvp, deliverOrder), opts); futureCollator.watchFuture(f, a); } retval = futureCollator.getResponseList(); } else if (mode == ResponseMode.GET_ALL) { // A SYNC call that needs to go everywhere Map<Address, Future<Object>> futures = new HashMap<>(dests.size()); for (Address dest : dests) futures.put( dest, card.sendMessageWithFuture( constructMessage(buf, dest, mode, rsvp, deliverOrder), opts)); retval = new RspList<>(); // a get() on each future will block till that call completes. for (Map.Entry<Address, Future<Object>> entry : futures.entrySet()) { Address target = entry.getKey(); try { retval.addRsp(target, entry.getValue().get(timeout, MILLISECONDS)); } catch (java.util.concurrent.TimeoutException te) { throw new TimeoutException( formatString( "Timed out after %s waiting for a response from %s", prettyPrintTime(timeout), target)); } catch (ExecutionException e) { if (ignoreLeavers && e.getCause() instanceof SuspectedException) { log.tracef(formatString("Ignoring node %s that left during the remote call", target)); } else { throw wrapThrowableInException(e.getCause()); } } } } else if (mode == ResponseMode.GET_NONE) { // An ASYNC call. We don't care about responses. for (Address dest : dests) card.sendMessage(constructMessage(buf, dest, mode, rsvp, deliverOrder), opts); } } // we only bother parsing responses if we are not in ASYNC mode. if (mode != ResponseMode.GET_NONE) { if (trace) log.tracef("Responses: %s", retval); // a null response is 99% likely to be due to a marshalling problem - we throw a NSE, this // needs to be changed when // JGroups supports http://jira.jboss.com/jira/browse/JGRP-193 // the serialization problem could be on the remote end and this is why we cannot catch this // above, when marshalling. if (retval == null) throw new NotSerializableException( "RpcDispatcher returned a null. This is most often caused by args for " + command.getClass().getSimpleName() + " not being serializable."); } return retval; }