/** * @param destination Member[] - destination.length > 0 * @param msg Serializable - the message to send * @param options sender options, options can trigger guarantee levels and different interceptors * to react to the message see class documentation for the <code>Channel</code> object.<br> * @param handler - callback object for error handling and completion notification, used when a * message is sent asynchronously using the <code>Channel.SEND_OPTIONS_ASYNCHRONOUS</code> * flag enabled. * @return UniqueId - the unique Id that was assigned to this message * @throws ChannelException - if an error occurs processing the message * @see org.apache.catalina.tribes.Channel */ @Override public UniqueId send(Member[] destination, Serializable msg, int options, ErrorHandler handler) throws ChannelException { if (msg == null) throw new ChannelException(sm.getString("groupChannel.nullMessage")); XByteBuffer buffer = null; try { if (destination == null || destination.length == 0) { throw new ChannelException(sm.getString("groupChannel.noDestination")); } ChannelData data = new ChannelData(true); // generates a unique Id data.setAddress(getLocalMember(false)); data.setTimestamp(System.currentTimeMillis()); byte[] b = null; if (msg instanceof ByteMessage) { b = ((ByteMessage) msg).getMessage(); options = options | SEND_OPTIONS_BYTE_MESSAGE; } else { b = XByteBuffer.serialize(msg); options = options & (~SEND_OPTIONS_BYTE_MESSAGE); } data.setOptions(options); // XByteBuffer buffer = new XByteBuffer(b.length+128,false); buffer = BufferPool.getBufferPool().getBuffer(b.length + 128, false); buffer.append(b, 0, b.length); data.setMessage(buffer); InterceptorPayload payload = null; if (handler != null) { payload = new InterceptorPayload(); payload.setErrorHandler(handler); } getFirstInterceptor().sendMessage(destination, data, payload); if (Logs.MESSAGES.isTraceEnabled()) { Logs.MESSAGES.trace( "GroupChannel - Sent msg:" + new UniqueId(data.getUniqueId()) + " at " + new java.sql.Timestamp(System.currentTimeMillis()) + " to " + Arrays.toNameString(destination)); Logs.MESSAGES.trace( "GroupChannel - Send Message:" + new UniqueId(data.getUniqueId()) + " is " + msg); } return new UniqueId(data.getUniqueId()); } catch (Exception x) { if (x instanceof ChannelException) throw (ChannelException) x; throw new ChannelException(x); } finally { if (buffer != null) BufferPool.getBufferPool().returnBuffer(buffer); } }
@Override public void messageReceived(ChannelMessage msg) { if (Logs.MESSAGES.isTraceEnabled()) { Logs.MESSAGES.trace( "ChannelCoordinator - Received msg:" + new UniqueId(msg.getUniqueId()) + " at " + new java.sql.Timestamp(System.currentTimeMillis()) + " from " + msg.getAddress().getName()); } super.messageReceived(msg); }
/** * Send a message to one or more members in the cluster * * @param destination Member[] - the destinations, null or zero length means all * @param msg ClusterMessage - the message to send * @param payload TBA */ @Override public void sendMessage(Member[] destination, ChannelMessage msg, InterceptorPayload payload) throws ChannelException { if (destination == null) destination = membershipService.getMembers(); if ((msg.getOptions() & Channel.SEND_OPTIONS_MULTICAST) == Channel.SEND_OPTIONS_MULTICAST) { membershipService.broadcast(msg); } else { clusterSender.sendMessage(msg, destination); } if (Logs.MESSAGES.isTraceEnabled()) { Logs.MESSAGES.trace( "ChannelCoordinator - Sent msg:" + new UniqueId(msg.getUniqueId()) + " at " + new java.sql.Timestamp(System.currentTimeMillis()) + " to " + Arrays.toNameString(destination)); } }
/** * Callback from the interceptor stack. <br> * When a message is received from a remote node, this method will be invoked by the previous * interceptor.<br> * This method can also be used to send a message to other components within the same application, * but its an extreme case, and you're probably better off doing that logic between the * applications itself. * * @param msg ChannelMessage */ @Override public void messageReceived(ChannelMessage msg) { if (msg == null) return; try { if (Logs.MESSAGES.isTraceEnabled()) { Logs.MESSAGES.trace( "GroupChannel - Received msg:" + new UniqueId(msg.getUniqueId()) + " at " + new java.sql.Timestamp(System.currentTimeMillis()) + " from " + msg.getAddress().getName()); } Serializable fwd = null; if ((msg.getOptions() & SEND_OPTIONS_BYTE_MESSAGE) == SEND_OPTIONS_BYTE_MESSAGE) { fwd = new ByteMessage(msg.getMessage().getBytes()); } else { try { fwd = XByteBuffer.deserialize( msg.getMessage().getBytesDirect(), 0, msg.getMessage().getLength()); } catch (Exception sx) { log.error(sm.getString("groupChannel.unable.deserialize", msg), sx); return; } } if (Logs.MESSAGES.isTraceEnabled()) { Logs.MESSAGES.trace( "GroupChannel - Receive Message:" + new UniqueId(msg.getUniqueId()) + " is " + fwd); } // get the actual member with the correct alive time Member source = msg.getAddress(); boolean rx = false; boolean delivered = false; for (int i = 0; i < channelListeners.size(); i++) { ChannelListener channelListener = (ChannelListener) channelListeners.get(i); if (channelListener != null && channelListener.accept(fwd, source)) { channelListener.messageReceived(fwd, source); delivered = true; // if the message was accepted by an RPC channel, that channel // is responsible for returning the reply, otherwise we send an absence reply if (channelListener instanceof RpcChannel) rx = true; } } // for if ((!rx) && (fwd instanceof RpcMessage)) { // if we have a message that requires a response, // but none was given, send back an immediate one sendNoRpcChannelReply((RpcMessage) fwd, source); } if (Logs.MESSAGES.isTraceEnabled()) { Logs.MESSAGES.trace( "GroupChannel delivered[" + delivered + "] id:" + new UniqueId(msg.getUniqueId())); } } catch (Exception x) { // this could be the channel listener throwing an exception, we should log it // as a warning. if (log.isWarnEnabled()) log.warn(sm.getString("groupChannel.receiving.error"), x); throw new RemoteProcessException("Exception:" + x.getMessage(), x); } }