package org.webpieces.nio.test.suns; import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.nio.channels.spi.AbstractSelector; import java.nio.channels.spi.SelectorProvider; import java.util.Iterator; import java.util.Set; import java.util.logging.Level; import org.webpieces.util.logging.Logger; import junit.framework.TestCase; /** * Previously internal review id: 498799 * * Weird....For a while, the selector keeps returning a keyset even after * key is cancelled, in 5.0_04, but not 5.0_03!!! * I switched to 5.0_03 and it started working. Switched back to 5.0_04 and it * started to work in that version. I will leave this code around for future use. * * @author Dean Hiller */ public class TestXPassDisconnectAfterRead extends TestCase { private static final Logger log = LoggerFactory.getLogger(TestXPassDisconnectAfterRead.class); private SelectorProvider provider; private AbstractSelector selector; private ServerSocketChannel server; private SocketChannel serverChannel; private SocketChannel client; // private String lastLock = "xyz"; private ByteBuffer buf = ByteBuffer.allocate(10); /** * @param name */ public TestXPassDisconnectAfterRead(String name) { super(name); } protected void setUp() throws Exception { provider = SelectorProvider.provider(); selector = provider.openSelector(); server = provider.openServerSocketChannel(); client = provider.openSocketChannel(); } private boolean receivedWrite = false; private boolean closeHappened = false; public void testDisconnectAfterReadResultsInNewKey() throws Exception { InetAddress loopBack = InetAddress.getByName("127.0.0.1"); InetSocketAddress clientAddr = new InetSocketAddress(loopBack, 0); InetSocketAddress serverAddr = new InetSocketAddress(loopBack, 0); server.configureBlocking(false); server.socket().bind(serverAddr); client.socket().bind(clientAddr); server.register(selector, SelectionKey.OP_ACCEPT); new PollingThread2().start(); SocketAddress addr = server.socket().getLocalSocketAddress(); client.connect(addr); log.info("configure client non-blocking"); client.configureBlocking(false); //client.register(selector, SelectionKey.OP_READ); // Thread.sleep(2000); log.info("write data to server"); ByteBuffer b = ByteBuffer.allocate(10); b.putChar('d'); b.putChar('e'); b.flip(); log.info("write bytes"); int i = client.write(b); log.info("wrote bytes="+i); synchronized(client) { log.info("waiting for server to tell us received data from read"); if(!receivedWrite) client.wait(); } client.close(); synchronized(client) { log.info("close done, notify server"); closeHappened = true; client.notify(); } log.info("sleeping"); //will block forever when bug is fixed..... // synchronized(lastLock) { // if(!isThreadDone) // lastLock.wait(); // } log.info("result="+result); Thread.sleep(5000); log.info("test done"); } //private boolean isThreadDone = false; private int result; private class PollingThread2 extends Thread { public void run() { try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } log.info("STARTING RUN LOOP"); int i = 0; while(true) { i++; runLoop2(); if(i > 10) break; } // synchronized (lastLock) { // result = i; // isThreadDone = true; // lastLock.notifyAll(); // } } } protected void runLoop2() { int numKeys = 0; try { log.info("going into selector"); numKeys = selector.select(); log.info("coming out with keys="+numKeys); } catch (IOException e) { log.error("Having trouble with a channel", e); } Set<SelectionKey> keySet = selector.selectedKeys(); Iterator<SelectionKey> iter = keySet.iterator(); while (iter.hasNext()) { try { SelectionKey theKey = iter.next(); log.info("in loop iter.next="+theKey+" isVal="+theKey.isValid()+" acc=" +theKey.isAcceptable()+" read="+theKey.isReadable()); if(theKey.isAcceptable()) { SocketChannel temp = server.accept(); if(temp != null) { serverChannel = temp; serverChannel.configureBlocking(false); log.info("register serverChannel"); serverChannel.register(selector, SelectionKey.OP_READ); } } else if(theKey.isReadable()) { log.info("reading bytes"); buf.clear(); int bytes = serverChannel.read(buf); log.info("read bytes="+bytes); iter.remove(); if(bytes < 0) theKey.cancel(); //keySet.remove(theKey); synchronized(client) { log.info("waiting for write"); receivedWrite = true; client.notify(); } synchronized(client) { log.info("received write but not close yet, wait for client to call close"); if(!closeHappened) client.wait(); } log.info("done waiting for close, it happened"); } } catch(Throwable e) { log.error("Processing of key failed, but continuing channel manager loop", e); } } keySet.clear(); } }