/** * Invokes a method in all members and expects responses from members contained in dests (or all * members if dests is null). * * @param dests A list of addresses. If null, we'll wait for responses from all cluster members * @param method_call The method (plus args) to be invoked * @param options A collection of call options, e.g. sync versus async, timeout etc * @param listener A FutureListener which will be registered (if non null) with the future * <em>before</em> the call is invoked * @return NotifyingFuture A future from which the results can be fetched * @throws Exception If the sending of the message threw an exception. Note that <em>no</em> * exception will be thrown if any of the target members threw an exception; such an exception * will be in the Rsp element for the particular member in the RspList */ public <T> NotifyingFuture<RspList<T>> callRemoteMethodsWithFuture( Collection<Address> dests, MethodCall method_call, RequestOptions options, FutureListener<RspList<T>> listener) throws Exception { if (dests != null && dests.isEmpty()) { // don't send if dest list is empty if (log.isTraceEnabled()) log.trace( "destination list of %s() is empty: no need to send message", method_call.getName()); return new NullFuture<>(new RspList()); } if (log.isTraceEnabled()) log.trace("dests=%s, method_call=%s, options=%s", dests, method_call, options); Buffer buf = req_marshaller != null ? req_marshaller.objectToBuffer(method_call) : Util.objectToBuffer(method_call); Message msg = new Message().setBuffer(buf); NotifyingFuture<RspList<T>> retval = super.castMessageWithFuture(dests, msg, options, listener); if (log.isTraceEnabled()) log.trace("responses: %s", retval); return retval; }
/** * Message contains MethodCall. Execute it against *this* object and return result. Use * MethodCall.invoke() to do this. Return result. */ public Object handle(Message req) throws Exception { if (server_obj == null) { log.error(Util.getMessage("NoMethodHandlerIsRegisteredDiscardingRequest")); return null; } if (req == null || req.getLength() == 0) { log.error(Util.getMessage("MessageOrMessageBufferIsNull")); return null; } Object body = req_marshaller != null ? req_marshaller.objectFromBuffer(req.getRawBuffer(), req.getOffset(), req.getLength()) : req.getObject(); if (!(body instanceof MethodCall)) throw new IllegalArgumentException("message does not contain a MethodCall object"); MethodCall method_call = (MethodCall) body; if (log.isTraceEnabled()) log.trace("[sender=%s], method_call: %s", req.getSrc(), method_call); if (method_call.getMode() == MethodCall.ID) { if (method_lookup == null) throw new Exception( String.format( "MethodCall uses ID=%d, but method_lookup has not been set", method_call.getId())); Method m = method_lookup.findMethod(method_call.getId()); if (m == null) throw new Exception("no method found for " + method_call.getId()); method_call.setMethod(m); } return method_call.invoke(server_obj); }
/** * Message contains MethodCall. Execute it against *this* object and return result. Use * MethodCall.invoke() to do this. Return result. */ public Object handle(Message req) { Object body; MethodCall method_call; if (server_obj == null) { if (log.isErrorEnabled()) log.error("no method handler is registered. Discarding request."); return null; } if (req == null || req.getLength() == 0) { if (log.isErrorEnabled()) log.error("message or message buffer is null"); return null; } try { body = req_marshaller != null ? req_marshaller.objectFromByteBuffer( req.getBuffer(), req.getOffset(), req.getLength()) : req.getObject(); } catch (Throwable e) { if (log.isErrorEnabled()) log.error("exception marshalling object", e); return e; } if (!(body instanceof MethodCall)) { if (log.isErrorEnabled()) log.error("message does not contain a MethodCall object"); // create an exception to represent this and return it return new IllegalArgumentException("message does not contain a MethodCall object"); } method_call = (MethodCall) body; try { if (log.isTraceEnabled()) log.trace("[sender=" + req.getSrc() + "], method_call: " + method_call); if (method_call.getMode() == MethodCall.ID) { if (method_lookup == null) throw new Exception( "MethodCall uses ID=" + method_call.getId() + ", but method_lookup has not been set"); Method m = method_lookup.findMethod(method_call.getId()); if (m == null) throw new Exception("no method found for " + method_call.getId()); method_call.setMethod(m); } return method_call.invoke(server_obj); } catch (Throwable x) { return x; } }
/** * Invokes a method in all members contained in dests (or all members if dests is null). * * @param dests A list of addresses. If null, the method will be invoked on all cluster members * @param method_call The method (plus args) to be invoked * @param options A collection of call options, e.g. sync versus async, timeout etc * @return RspList A list of return values and flags (suspected, not received) per member * @since 2.9 */ public RspList callRemoteMethods( Collection<Address> dests, MethodCall method_call, RequestOptions options) { if (dests != null && dests.isEmpty()) { // don't send if dest list is empty if (log.isTraceEnabled()) log.trace( new StringBuilder("destination list of ") .append(method_call.getName()) .append("() is empty: no need to send message")); return RspList.EMPTY_RSP_LIST; } if (log.isTraceEnabled()) log.trace( new StringBuilder("dests=") .append(dests) .append(", method_call=") .append(method_call) .append(", options=") .append(options)); Object buf; try { buf = req_marshaller != null ? req_marshaller.objectToBuffer(method_call) : Util.objectToByteBuffer(method_call); } catch (Exception e) { // if(log.isErrorEnabled()) log.error("exception", e); // we will change this in 3.0 to add the exception to the signature // (see http://jira.jboss.com/jira/browse/JGRP-193). The reason for a RTE is that we cannot // change the // signature in 2.3, otherwise 2.3 would be *not* API compatible to prev releases throw new RuntimeException("failure to marshal argument(s)", e); } Message msg = new Message(); if (buf instanceof Buffer) msg.setBuffer((Buffer) buf); else msg.setBuffer((byte[]) buf); msg.setFlag(options.getFlags()); if (options.getScope() > 0) msg.setScope(options.getScope()); RspList retval = super.castMessage(dests, msg, options); if (log.isTraceEnabled()) log.trace("responses: " + retval); return retval; }
public Buffer objectToBuffer(Object obj) throws Exception { MethodCall call = (MethodCall) obj; ByteBuffer buf; switch (call.getId()) { case START: case GET_CONFIG: buf = ByteBuffer.allocate(Global.BYTE_SIZE); buf.put((byte) call.getId()); return new Buffer(buf.array()); case SET_OOB: case SET_SYNC: return new Buffer(booleanBuffer(call.getId(), (Boolean) call.getArgs()[0])); case SET_NUM_MSGS: case SET_NUM_THREADS: case SET_MSG_SIZE: case SET_ANYCAST_COUNT: return new Buffer(intBuffer(call.getId(), (Integer) call.getArgs()[0])); case GET: return new Buffer(longBuffer(call.getId(), (Long) call.getArgs()[0])); case PUT: Long long_arg = (Long) call.getArgs()[0]; byte[] arg2 = (byte[]) call.getArgs()[1]; buf = ByteBuffer.allocate( Global.BYTE_SIZE + Global.INT_SIZE + Global.LONG_SIZE + arg2.length); buf.put((byte) call.getId()) .putLong(long_arg) .putInt(arg2.length) .put(arg2, 0, arg2.length); return new Buffer(buf.array()); case SET_READ_PERCENTAGE: Double double_arg = (Double) call.getArgs()[0]; buf = ByteBuffer.allocate(Global.BYTE_SIZE + Global.DOUBLE_SIZE); buf.put((byte) call.getId()).putDouble(double_arg); return new Buffer(buf.array()); default: throw new IllegalStateException("method " + call.getMethod() + " not known"); } }