You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by te...@apache.org on 2007/02/06 18:26:13 UTC

svn commit: r504210 - in /harmony/enhanced/classlib/trunk/modules: luni/src/main/java/org/apache/harmony/luni/platform/ nio/src/main/java/org/apache/harmony/nio/internal/ nio/src/test/java/common/org/apache/harmony/nio/tests/java/nio/channels/

Author: tellison
Date: Tue Feb  6 09:26:11 2007
New Revision: 504210

URL: http://svn.apache.org/viewvc?view=rev&rev=504210
Log:
Apply patch HARMONY-3122 ([classlib][nio]refine Selector.select() implementation)

Modified:
    harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/platform/INetworkSystem.java
    harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/platform/OSNetworkSystem.java
    harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/SelectorImpl.java
    harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/ServerSocketChannelImpl.java
    harmony/enhanced/classlib/trunk/modules/nio/src/test/java/common/org/apache/harmony/nio/tests/java/nio/channels/SocketChannelTest.java

Modified: harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/platform/INetworkSystem.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/platform/INetworkSystem.java?view=diff&rev=504210&r1=504209&r2=504210
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/platform/INetworkSystem.java (original)
+++ harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/platform/INetworkSystem.java Tue Feb  6 09:26:11 2007
@@ -170,9 +170,9 @@
 	public InetAddress getSocketLocalAddress(FileDescriptor aFD,
 			boolean preferIPv6Addresses);
 
-	public int[] select(SelectableChannel[] readChannels,
-			SelectableChannel[] writeChannels, long timeout)
-			throws SocketException;
+    public int[] select(FileDescriptor[] readFDs,
+            FileDescriptor[] writeFDs, long timeout)
+            throws SocketException;
 
 	/*
 	 * Query the IP stack for the local port to which this socket is bound.

Modified: harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/platform/OSNetworkSystem.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/platform/OSNetworkSystem.java?view=diff&rev=504210&r1=504209&r2=504210
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/platform/OSNetworkSystem.java (original)
+++ harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/platform/OSNetworkSystem.java Tue Feb  6 09:26:11 2007
@@ -288,41 +288,18 @@
      *      SocketException @return int array, each int approve one of the	 * channel if OK
 	 */
 
-	public int[] select(SelectableChannel[] readChannels,
-			SelectableChannel[] writeChannels, long timeout)
+	public int[] select(FileDescriptor[] readFDs,
+            FileDescriptor[] writeFDs, long timeout)
 			throws SocketException {
-
-		FileDescriptor fdHandler = null;
-		int countRead = readChannels.length;
-		int countWrite = writeChannels.length;
-		int result = 0, val;
-		FileDescriptor[] readFDs = new FileDescriptor[countRead];
+		int countRead = readFDs.length;
+		int countWrite = writeFDs.length;
+		int result = 0;
+        if (0 == countRead + countWrite) {
+            return (new int[0]);
+        }
 		int[] flags = new int[countRead + countWrite];
 
-		if ((0 == readChannels.length) && (0 == writeChannels.length)) {
-			return (new int[0]);
-		}
-		for (val = 0; val < countRead; val++, fdHandler = null) {
-			SelectableChannel element = readChannels[val];
-			if (element instanceof FileDescriptorHandler) {
-				fdHandler = ((FileDescriptorHandler) element).getFD();
-			}
-			if (null != fdHandler) {
-				readFDs[val] = fdHandler;
-			}
-		}
-		FileDescriptor[] writeFDs = new FileDescriptor[countWrite];
-		for (val = 0; val < countWrite; val++, fdHandler = null) {
-			SelectableChannel element = writeChannels[val];
-            if (element instanceof FileDescriptorHandler) {
-                fdHandler = ((FileDescriptorHandler) element).getFD();
-            }
-			if (null != fdHandler) {
-				writeFDs[val] = fdHandler;
-			}
-		}
-
-		// handle timeout in native
+        // handle timeout in native
 		result = selectImpl(readFDs, writeFDs, countRead, countWrite, flags,
 				timeout);
 

Modified: harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/SelectorImpl.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/SelectorImpl.java?view=diff&rev=504210&r1=504209&r2=504210
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/SelectorImpl.java (original)
+++ harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/SelectorImpl.java Tue Feb  6 09:26:11 2007
@@ -15,6 +15,7 @@
  */
 package org.apache.harmony.nio.internal;
 
+import java.io.FileDescriptor;
 import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.nio.channels.ClosedSelectorException;
@@ -36,7 +37,7 @@
 import java.util.List;
 import java.util.Set;
 
-import org.apache.harmony.luni.platform.INetworkSystem;
+import org.apache.harmony.luni.platform.FileDescriptorHandler;
 import org.apache.harmony.luni.platform.Platform;
 
 /*
@@ -77,14 +78,20 @@
     private Pipe.SinkChannel sink;
 
     private Pipe.SourceChannel source;
+    
+    private FileDescriptor sourcefd;
+    
+    private SelectionKey[] readableChannels;
 
-    private List<SelectableChannel> readableChannels = new ArrayList<SelectableChannel>();
+    private SelectionKey[] writableChannels;
 
-    private List<SelectableChannel> writableChannels = new ArrayList<SelectableChannel>();
+    private List<FileDescriptor> readableFDs = new ArrayList<FileDescriptor>();
 
-    private SelectableChannel[] readable;
+    private List<FileDescriptor> writableFDs = new ArrayList<FileDescriptor>();
 
-    private SelectableChannel[] writable;
+    private FileDescriptor[] readable;
+
+    private FileDescriptor[] writable;
 
     public SelectorImpl(SelectorProvider selectorProvider) {
         super(selectorProvider);
@@ -92,6 +99,7 @@
             Pipe mockSelector = selectorProvider.openPipe();
             sink = mockSelector.sink();
             source = mockSelector.source();
+            sourcefd = ((FileDescriptorHandler)source).getFD();
             source.configureBlocking(false);
         } catch (IOException e) {
             // do nothing
@@ -172,7 +180,26 @@
             synchronized (keys) {
                 synchronized (selectedKeys) {
                     doCancel();
-                    return selectImpl(timeout);
+                    int[] readyChannels = null;
+                    boolean isBlock = (SELECT_NOW != timeout);
+                    if (keys.size() == 0) {
+                        return 0;
+                    }
+                    prepareChannels();
+                    try {
+                        if (isBlock) {
+                            begin();
+                        }
+                        readyChannels = Platform.getNetworkSystem().select(readable, writable, timeout);
+                    } finally {
+                        // clear results for next select
+                        readableFDs.clear();
+                        writableFDs.clear();                        
+                        if (isBlock) {
+                            end();
+                        }
+                    }
+                    return processSelectResult(readyChannels);                    
                 }
             }
         }
@@ -188,25 +215,31 @@
 
     // Prepares and adds channels to list for selection
     private void prepareChannels() {
-        readableChannels.add(source);
+        readableFDs.add(sourcefd);        
+        List<SelectionKey> readChannelList = new ArrayList<SelectionKey>();
+        readChannelList.add(source.keyFor(this));
+        List<SelectionKey> writeChannelList = new ArrayList<SelectionKey>();
         synchronized (keysLock) {
             for (Iterator<SelectionKey> i = keys.iterator(); i.hasNext();) {
                 SelectionKeyImpl key = (SelectionKeyImpl) i.next();
                 key.oldInterestOps = key.interestOps();
                 boolean isReadableChannel = ((SelectionKey.OP_ACCEPT | SelectionKey.OP_READ) & key.oldInterestOps) != 0;
                 boolean isWritableChannel = ((SelectionKey.OP_CONNECT | SelectionKey.OP_WRITE) & key.oldInterestOps) != 0;
+                SelectableChannel channel = key.channel();                  
                 if (isReadableChannel) {
-                    readableChannels.add(key.channel());
+                    readChannelList.add(channel.keyFor(this));
+                    readableFDs.add(((FileDescriptorHandler)channel).getFD());
                 }
                 if (isWritableChannel) {
-                    writableChannels.add(key.channel());
+                    writeChannelList.add(channel.keyFor(this));
+                    writableFDs.add(((FileDescriptorHandler)channel).getFD());
                 }
             }
         }
-        readable = readableChannels.toArray(new SelectableChannel[0]);
-        writable = writableChannels.toArray(new SelectableChannel[0]);
-        readableChannels.clear();
-        writableChannels.clear();
+        readableChannels = readChannelList.toArray(new SelectionKey[0]);
+        writableChannels = writeChannelList.toArray(new SelectionKey[0]);
+        readable = readableFDs.toArray(new FileDescriptor[0]);
+        writable = writableFDs.toArray(new FileDescriptor[0]);
     }
 
     // Analyses selected channels and adds keys of ready channels to
@@ -223,10 +256,10 @@
             }
         }
         int selected = 0;
-        for (int i = 1; i < readyChannels.length; i++) {
-            SelectionKeyImpl key = (SelectionKeyImpl) (i >= readable.length ? writable[i
-                    - readable.length].keyFor(this)
-                    : readable[i].keyFor(this));
+        for (int i = 1; i < readyChannels.length; i++) {            
+            SelectionKeyImpl key = (SelectionKeyImpl) (i >= readable.length ? writableChannels[i
+                    - readable.length]
+                    : readableChannels[i]);
             if (null == key) {
                 continue;
             }
@@ -261,28 +294,9 @@
                 }
             }
         }
+        readableChannels = null;
+        writableChannels = null;
         return selected;
-    }
-
-    private int selectImpl(long timeout) throws IOException {
-        INetworkSystem os = Platform.getNetworkSystem();
-        int[] readyChannels = null;
-        boolean isBlock = (SELECT_NOW != timeout);
-        if (keys.size() == 0) {
-            return 0;
-        }
-        prepareChannels();
-        try {
-            if (isBlock) {
-                begin();
-            }
-            readyChannels = os.select(readable, writable, timeout);
-        } finally {
-            if (isBlock) {
-                end();
-            }
-        }
-        return processSelectResult(readyChannels);
     }
 
     /*

Modified: harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/ServerSocketChannelImpl.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/ServerSocketChannelImpl.java?view=diff&rev=504210&r1=504209&r2=504210
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/ServerSocketChannelImpl.java (original)
+++ harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/ServerSocketChannelImpl.java Tue Feb  6 09:26:11 2007
@@ -141,8 +141,8 @@
                         // for non blocking mode, use select to see whether
                         // there are any pending connections.
                         int[] tryResult = Platform.getNetworkSystem().select(
-                                new SelectableChannel[] { this },
-                                new SelectableChannel[0], 0);
+                                new FileDescriptor[] { this.fd },
+                                new FileDescriptor[0], 0);
                         if (0 == tryResult.length || 0 == tryResult[0]) {
                             // no pending connections, returns immediately.
                             return null;

Modified: harmony/enhanced/classlib/trunk/modules/nio/src/test/java/common/org/apache/harmony/nio/tests/java/nio/channels/SocketChannelTest.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/nio/src/test/java/common/org/apache/harmony/nio/tests/java/nio/channels/SocketChannelTest.java?view=diff&rev=504210&r1=504209&r2=504210
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/nio/src/test/java/common/org/apache/harmony/nio/tests/java/nio/channels/SocketChannelTest.java (original)
+++ harmony/enhanced/classlib/trunk/modules/nio/src/test/java/common/org/apache/harmony/nio/tests/java/nio/channels/SocketChannelTest.java Tue Feb  6 09:26:11 2007
@@ -1246,8 +1246,11 @@
 
     public void testCFII_EmptyHost() throws Exception {
         statusNotConnected_NotPending();
+        ServerSocket server = new ServerSocket(0);
+        int port = server.getLocalPort();
+        server.close();
         try {
-            this.channel1.connect(new InetSocketAddress("", 1081));
+            this.channel1.connect(new InetSocketAddress("", port));
             fail("Should throw ConnectException");
         } catch (ConnectException e) {
             // correct
@@ -1952,9 +1955,42 @@
         } catch (ClosedChannelException e) {
             // correct
         }
-
     }
 
+    public void testReadByteBuffer_Direct() throws Exception {
+        assertTrue(this.server1.isBound());
+        java.nio.ByteBuffer readBuf = java.nio.ByteBuffer
+                .allocateDirect(CAPACITY_NORMAL);
+        assertFalse(this.channel1.isRegistered());
+        assertTrue(this.channel1.isBlocking());
+        assertFalse(this.channel1.isConnected());
+        assertFalse(this.channel1.isConnectionPending());
+        assertTrue(this.channel1.isOpen());
+        // note: blocking-mode will make the read process endless!
+        this.channel1.configureBlocking(false);
+        try {
+            channel1.read(readBuf);
+            fail("Should throw NotYetConnectedException");
+        } catch (NotYetConnectedException e) {
+            // correct
+        }
+        this.channel1.connect(localAddr1);
+        assertFalse(this.channel1.isBlocking());
+        assertTrue(this.channel1.isConnectionPending());
+        assertFalse(this.channel1.isConnected());
+        if (tryFinish()) {
+            assertEquals(0, this.channel1.read(readBuf));
+        }
+
+        this.channel1.close();
+        try {
+            channel1.read(readBuf);
+            fail("Should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // correct
+        }
+    }
+    
     public void testReadByteBuffer_BufNull() throws Exception {
         assertTrue(this.server1.isBound());
         java.nio.ByteBuffer readBuf = java.nio.ByteBuffer.allocate(0);
@@ -2023,6 +2059,45 @@
             // correct
         }
     }
+    
+    /*
+     * SocketChannelImpl.read(ByteBuffer[], int, int)'
+     */
+    public void testReadByteBufferArrayIntInt_Direct() throws Exception {
+        assertTrue(this.server1.isBound());
+        java.nio.ByteBuffer[] readBuf = new java.nio.ByteBuffer[2];
+        readBuf[0] = java.nio.ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+        readBuf[1] = java.nio.ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+        assertFalse(this.channel1.isRegistered());
+        assertTrue(this.channel1.isBlocking());
+        assertFalse(this.channel1.isConnected());
+        assertFalse(this.channel1.isConnectionPending());
+        assertTrue(this.channel1.isOpen());
+        // note: blocking-mode will make the read process endless!
+        this.channel1.configureBlocking(false);
+        try {
+            channel1.read(readBuf, 0, 1);
+            fail("Should throw NotYetConnectedException");
+        } catch (NotYetConnectedException e) {
+            // correct
+        }
+        this.channel1.connect(localAddr1);
+        assertFalse(this.channel1.isBlocking());
+        assertTrue(this.channel1.isConnectionPending());
+        assertFalse(this.channel1.isConnected());
+        if (tryFinish()) {
+            assertEquals(0, this.channel1.read(readBuf, 0, 1));
+            assertEquals(0, this.channel1.read(readBuf, 0, 2));
+        }
+
+        this.channel1.close();
+        try {
+            channel1.read(readBuf, 0, 1);
+            fail("Should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // correct
+        }
+    }
 
     public void testReadByteBufferArrayIntInt_BufNull() throws Exception {
         assertTrue(this.server1.isBound());
@@ -2098,6 +2173,37 @@
             // correct
         }
     }
+    
+    public void testWriteByteBuffer_Direct() throws IOException {
+        assertTrue(this.server1.isBound());
+        java.nio.ByteBuffer writeBuf = java.nio.ByteBuffer
+                .allocateDirect(CAPACITY_NORMAL);
+        assertFalse(this.channel1.isRegistered());
+        assertTrue(this.channel1.isBlocking());
+        assertFalse(this.channel1.isConnected());
+        assertFalse(this.channel1.isConnectionPending());
+        assertTrue(this.channel1.isOpen());
+        try {
+            channel1.write(writeBuf);
+            fail("Should throw NotYetConnectedException");
+        } catch (NotYetConnectedException e) {
+            // correct
+        }
+        this.channel1.connect(localAddr1);
+        assertTrue(this.channel1.isBlocking());
+        assertTrue(this.channel1.isConnected());
+        assertFalse(this.channel1.isConnectionPending());
+        assertTrue(this.channel1.isOpen());
+        assertEquals(CAPACITY_NORMAL, this.channel1.write(writeBuf));
+
+        this.channel1.close();
+        try {
+            channel1.write(writeBuf);
+            fail("Should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // correct
+        }
+    }
 
     public void testWriteByteBuffer_BufNull() throws IOException {
         assertTrue(this.server1.isBound());
@@ -2150,6 +2256,44 @@
         }
     }
 
+    /*
+     * SocketChannelImpl.write(ByteBuffer[], int, int)'
+     */
+    public void testWriteByteBufferArrayIntInt_Direct() throws IOException {
+        java.nio.ByteBuffer[] writeBuf = new java.nio.ByteBuffer[2];
+        writeBuf[0] = java.nio.ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+        writeBuf[1] = java.nio.ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+        assertFalse(this.channel1.isRegistered());
+        assertTrue(this.channel1.isBlocking());
+        assertFalse(this.channel1.isConnected());
+        assertFalse(this.channel1.isConnectionPending());
+        assertTrue(this.channel1.isOpen());
+        try {
+            channel1.write(writeBuf, 0, 1);
+            fail("Should throw NotYetConnectedException");
+        } catch (NotYetConnectedException e) {
+            // correct
+        }
+        this.channel1.connect(localAddr1);
+        assertTrue(this.channel1.isBlocking());
+        assertTrue(this.channel1.isConnected());
+        assertFalse(this.channel1.isConnectionPending());
+        assertTrue(this.channel1.isOpen());
+        assertEquals(CAPACITY_NORMAL, this.channel1.write(writeBuf, 0, 1));
+        // still writes the same size as above
+        assertEquals(CAPACITY_NORMAL, this.channel1.write(writeBuf, 0, 2));
+        writeBuf[0].flip();
+        writeBuf[1].flip();
+        assertEquals(CAPACITY_NORMAL * 2, this.channel1.write(writeBuf, 0, 2));
+        this.channel1.close();
+        try {
+            channel1.write(writeBuf);
+            fail("Should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // correct
+        }
+    }
+    
     public void testWriteByteBufferArrayIntInt_BufNull() throws IOException {
         java.nio.ByteBuffer[] writeBuf = new java.nio.ByteBuffer[0];