/** * Wait for Acknowledgement from other server. FIXME Please, not wait only for three characters, * better control that the wait ack message is correct. * * @throws java.io.IOException * @throws java.net.SocketTimeoutException */ protected void waitForAck() throws java.io.IOException { try { boolean ackReceived = false; boolean failAckReceived = false; ackbuf.clear(); int bytesRead = 0; int i = soIn.read(); while ((i != -1) && (bytesRead < Constants.ACK_COMMAND.length)) { bytesRead++; byte d = (byte) i; ackbuf.append(d); if (ackbuf.doesPackageExist()) { byte[] ackcmd = ackbuf.extractDataPackage(true).getBytes(); ackReceived = Arrays.equals(ackcmd, org.apache.catalina.tribes.transport.Constants.ACK_DATA); failAckReceived = Arrays.equals(ackcmd, org.apache.catalina.tribes.transport.Constants.FAIL_ACK_DATA); ackReceived = ackReceived || failAckReceived; break; } i = soIn.read(); } if (!ackReceived) { if (i == -1) throw new IOException( sm.getString( "IDataSender.ack.eof", getAddress(), new Integer(socket.getLocalPort()))); else throw new IOException( sm.getString( "IDataSender.ack.wrong", getAddress(), new Integer(socket.getLocalPort()))); } else if (failAckReceived && getThrowOnFailedAck()) { throw new RemoteProcessException( "Received a failed ack:org.apache.catalina.tribes.transport.Constants.FAIL_ACK_DATA"); } } catch (IOException x) { String errmsg = sm.getString( "IDataSender.ack.missing", getAddress(), new Integer(socket.getLocalPort()), new Long(getTimeout())); if (SenderState.getSenderState(getDestination()).isReady()) { SenderState.getSenderState(getDestination()).setSuspect(); if (log.isWarnEnabled()) log.warn(errmsg, x); } else { if (log.isDebugEnabled()) log.debug(errmsg, x); } throw x; } finally { ackbuf.clear(); } }
/** * @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); } }
public static void main(String[] args) throws Exception { Member mbr = new MemberImpl("localhost", 9999, 0); ChannelData data = new ChannelData(); data.setOptions(Channel.SEND_OPTIONS_BYTE_MESSAGE); data.setAddress(mbr); byte[] buf = new byte[8192 * 4]; data.setMessage(new XByteBuffer(buf, false)); buf = XByteBuffer.createDataPackage(data); int len = buf.length; System.out.println("Message size:" + len + " bytes"); BigDecimal total = new BigDecimal((double) 0); BigDecimal bytes = new BigDecimal((double) len); Socket socket = new Socket("localhost", 9999); System.out.println("Writing to 9999"); OutputStream out = socket.getOutputStream(); long start = 0; double mb = 0; boolean first = true; int count = 0; DecimalFormat df = new DecimalFormat("##.00"); while (count < 1000000) { if (first) { first = false; start = System.currentTimeMillis(); } out.write(buf, 0, buf.length); mb += ((double) buf.length) / 1024 / 1024; total = total.add(bytes); if (((++count) % 10000) == 0) { long time = System.currentTimeMillis(); double seconds = ((double) (time - start)) / 1000; System.out.println( "Throughput " + df.format(mb / seconds) + " MB/seconds messages " + count + ", total " + mb + " MB, total " + total + " bytes."); } } out.flush(); System.out.println("Complete, sleeping 5 seconds"); Thread.sleep(5000); }
protected static boolean memberAlive( Member mbr, byte[] msgData, boolean sendTest, boolean readTest, long readTimeout, long conTimeout, int optionFlag) { // could be a shutdown notification if (Arrays.equals(mbr.getCommand(), Member.SHUTDOWN_PAYLOAD)) return false; Socket socket = new Socket(); try { InetAddress ia = InetAddress.getByAddress(mbr.getHost()); InetSocketAddress addr = new InetSocketAddress(ia, mbr.getPort()); socket.setSoTimeout((int) readTimeout); socket.connect(addr, (int) conTimeout); if (sendTest) { ChannelData data = new ChannelData(true); data.setAddress(mbr); data.setMessage(new XByteBuffer(msgData, false)); data.setTimestamp(System.currentTimeMillis()); int options = optionFlag | Channel.SEND_OPTIONS_BYTE_MESSAGE; if (readTest) options = (options | Channel.SEND_OPTIONS_USE_ACK); else options = (options & (~Channel.SEND_OPTIONS_USE_ACK)); data.setOptions(options); byte[] message = XByteBuffer.createDataPackage(data); socket.getOutputStream().write(message); if (readTest) { int length = socket.getInputStream().read(message); return length > 0; } } // end if return true; } catch (SocketTimeoutException sx) { // do nothing, we couldn't connect } catch (ConnectException cx) { // do nothing, we couldn't connect } catch (Exception x) { log.error("Unable to perform failure detection check, assuming member down.", x); } finally { try { socket.close(); } catch (Exception ignore) { } } return false; }
@Override public void messageReceived(ChannelMessage msg) { if (!okToProcess(msg.getOptions())) { super.messageReceived(msg); return; } int msgnr = XByteBuffer.toInt(msg.getMessage().getBytesDirect(), msg.getMessage().getLength() - 4); msg.getMessage().trim(4); MessageOrder order = new MessageOrder(msgnr, (ChannelMessage) msg.deepclone()); try { inLock.writeLock().lock(); if (processIncoming(order)) processLeftOvers(msg.getAddress(), false); } finally { inLock.writeLock().unlock(); } }
public static Data createRandomData(int size, int number) { int i = r.nextInt(); i = (i % 127); int length = Math.abs(r.nextInt() % size); if (length < 100) length += 100; Data d = new Data(); d.length = length; d.key = (byte) i; d.data = new byte[length]; Arrays.fill(d.data, d.key); if (number > 0 && d.data.length >= 4) { // populate number d.hasNr = true; XByteBuffer.toBytes(number, d.data, 0); } return d; }
@Override public void broadcast(ChannelMessage message) throws ChannelException { if (impl == null || (impl.startLevel & Channel.MBR_TX_SEQ) != Channel.MBR_TX_SEQ) throw new ChannelException(sm.getString("mcastService.noStart")); byte[] data = XByteBuffer.createDataPackage((ChannelData) message); if (data.length > McastServiceImpl.MAX_PACKET_SIZE) { throw new ChannelException( sm.getString( "mcastService.exceed.maxPacketSize", Integer.toString(data.length), Integer.toString(McastServiceImpl.MAX_PACKET_SIZE))); } DatagramPacket packet = new DatagramPacket(data, 0, data.length); try { impl.send(false, packet); } catch (Exception x) { throw new ChannelException(x); } }
public int getNumber() { if (!hasNr) return -1; return XByteBuffer.toInt(this.data, 0); }
public static void main(String[] args) throws Exception { Selector selector = Selector.open(); Member mbr = new MemberImpl("localhost", 9999, 0); ChannelData data = new ChannelData(); data.setOptions(Channel.SEND_OPTIONS_BYTE_MESSAGE); data.setAddress(mbr); byte[] buf = new byte[8192 * 4]; data.setMessage(new XByteBuffer(buf, false)); buf = XByteBuffer.createDataPackage(data); int len = buf.length; BigDecimal total = new BigDecimal((double) 0); BigDecimal bytes = new BigDecimal((double) len); NioSender sender = new NioSender(); sender.setDestination(mbr); sender.setDirectBuffer(true); sender.setSelector(selector); sender.setTxBufSize(1024 * 1024); sender.connect(); sender.setMessage(buf); System.out.println("Writing to 9999"); long start = 0; double mb = 0; boolean first = true; int count = 0; DecimalFormat df = new DecimalFormat("##.00"); while (count < 100000) { if (first) { first = false; start = System.currentTimeMillis(); } sender.setMessage(buf); int selectedKeys = 0; try { selectedKeys = selector.select(0); } catch (Exception e) { e.printStackTrace(); continue; } if (selectedKeys == 0) { continue; } Iterator it = selector.selectedKeys().iterator(); while (it.hasNext()) { SelectionKey sk = (SelectionKey) it.next(); it.remove(); try { int readyOps = sk.readyOps(); sk.interestOps(sk.interestOps() & ~readyOps); if (sender.process(sk, false)) { total = total.add(bytes); sender.reset(); sender.setMessage(buf); mb += ((double) len) / 1024 / 1024; if (((++count) % 10000) == 0) { long time = System.currentTimeMillis(); double seconds = ((double) (time - start)) / 1000; System.out.println( "Throughput " + df.format(mb / seconds) + " MB/seconds, total " + mb + " MB, total " + total + " bytes."); } } } catch (Throwable t) { t.printStackTrace(); return; } } selector.selectedKeys().clear(); } System.out.println("Complete, sleeping 15 seconds"); Thread.sleep(15000); }
/** * 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); } }