package edu.washington.escience.myria.parallel.ipc; import static org.jboss.netty.channel.Channels.fireChannelClosed; import static org.jboss.netty.channel.Channels.fireChannelDisconnected; import static org.jboss.netty.channel.Channels.fireChannelUnbound; import java.net.SocketAddress; import org.jboss.netty.channel.AbstractChannel; import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.ChannelConfig; import org.jboss.netty.channel.ChannelFuture; import org.jboss.netty.channel.ChannelPipeline; import org.jboss.netty.channel.ChannelSink; import org.jboss.netty.channel.Channels; import org.jboss.netty.channel.local.LocalAddress; import org.jboss.netty.channel.local.LocalChannel; import org.slf4j.LoggerFactory; /** * The Channel used when the sender and the receiver are actually in the same JVM. * */ public class InJVMChannel extends AbstractChannel implements LocalChannel { /** The logger for this class. */ protected static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(InJVMChannel.class); /** * Messages will be processed by the pipeline first and if the pipeline decides not to filter out a message, then it * will finally reach the sink. * * @param localInJVMPipeline the pipeline to execute when events happen on this channel. * @param localInJVMChannelSink the message sink * */ public InJVMChannel( final ChannelPipeline localInJVMPipeline, final ChannelSink localInJVMChannelSink) { super(null, null, localInJVMPipeline, localInJVMChannelSink); localAddr = new LocalAddress(LocalAddress.EPHEMERAL); Channels.fireChannelOpen(this); } /** * The pseudo local address of this channel. * */ private final LocalAddress localAddr; /** * A pseudo server address for use as the server address of all {@link InJVMChannel}s. * */ static final LocalAddress PSEUDO_SERVER_ADDRESS = new LocalAddress(LocalAddress.EPHEMERAL); @Override public final ChannelFuture bind(final SocketAddress localAddress) { throw new UnsupportedOperationException(); } /** * close the channel. Should be called by the sink. * * @param cf the close channel future. * */ final void closeNow(final ChannelFuture cf) { // Close the self. if (!setClosed()) { return; } fireChannelDisconnected(this); fireChannelUnbound(this); fireChannelClosed(this); cf.setSuccess(); } @Override public final ChannelFuture setInterestOps(final int interestOps) { int newIOPS = interestOps; if ((interestOps & OP_READ) != OP_READ) { // server side stop read => client side stop write. newIOPS = interestOps | Channel.OP_WRITE; } else { newIOPS = interestOps & ~Channel.OP_WRITE; } return super.setInterestOps(newIOPS); } @Override protected final void setInterestOpsNow(final int interestOps) { super.setInterestOpsNow(interestOps); } @Override public final ChannelFuture connect(final SocketAddress remoteAddress) { throw new UnsupportedOperationException(); } @Override public final ChannelFuture disconnect() { return close(); } @Override public final ChannelFuture unbind() { return close(); } @Override public final boolean isBound() { return isOpen(); } @Override public final boolean isConnected() { return isOpen(); } @Override public final ChannelFuture write(final Object message, final SocketAddress remoteAddress) { return write(message); } @Override public final ChannelConfig getConfig() { return null; } @Override public final LocalAddress getLocalAddress() { return localAddr; } @Override public final LocalAddress getRemoteAddress() { return PSEUDO_SERVER_ADDRESS; } }