You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by mh...@apache.org on 2007/12/27 22:34:56 UTC

svn commit: r607125 - in /mina/trunk/core/src: main/java/org/apache/mina/common/ main/java/org/apache/mina/transport/socket/nio/ test/java/org/apache/mina/transport/ test/java/org/apache/mina/transport/socket/nio/

Author: mheath
Date: Thu Dec 27 13:34:55 2007
New Revision: 607125

URL: http://svn.apache.org/viewvc?rev=607125&view=rev
Log:
Fixed DIRMINA-503.
Added tests for sending files with FileRegion.
Fixed FileRegion creation code in AbstractIoSession.

Added:
    mina/trunk/core/src/test/java/org/apache/mina/transport/AbstractFileRegionTest.java   (with props)
    mina/trunk/core/src/test/java/org/apache/mina/transport/socket/nio/NioFileRegionTest.java   (with props)
Modified:
    mina/trunk/core/src/main/java/org/apache/mina/common/AbstractIoSession.java
    mina/trunk/core/src/main/java/org/apache/mina/common/AbstractPollingIoProcessor.java
    mina/trunk/core/src/main/java/org/apache/mina/transport/socket/nio/NioProcessor.java

Modified: mina/trunk/core/src/main/java/org/apache/mina/common/AbstractIoSession.java
URL: http://svn.apache.org/viewvc/mina/trunk/core/src/main/java/org/apache/mina/common/AbstractIoSession.java?rev=607125&r1=607124&r2=607125&view=diff
==============================================================================
--- mina/trunk/core/src/main/java/org/apache/mina/common/AbstractIoSession.java (original)
+++ mina/trunk/core/src/main/java/org/apache/mina/common/AbstractIoSession.java Thu Dec 27 13:34:55 2007
@@ -281,35 +281,32 @@
             return future;
         }
 
-        FileChannel channel = null;
-        if (message instanceof IoBuffer
-                && !((IoBuffer) message).hasRemaining()) {
-            throw new IllegalArgumentException(
-                    "message is empty. Forgot to call flip()?");
-        } else if (message instanceof FileChannel) {
-            channel = (FileChannel) message;
-            try {
-                message = new DefaultFileRegion(channel, 0, channel.size());
-            } catch (IOException e) {
-                ExceptionMonitor.getInstance().exceptionCaught(e);
-                return DefaultWriteFuture.newNotWrittenFuture(this, e);
-            }
-        } else if (message instanceof File) {
-            File file = (File) message;
-            try {
-                channel = new FileInputStream(file).getChannel();
-            } catch (IOException e) {
-                ExceptionMonitor.getInstance().exceptionCaught(e);
-                return DefaultWriteFuture.newNotWrittenFuture(this, e);
+        FileChannel openedFileChannel = null;
+        try {
+            if (message instanceof IoBuffer
+                    && !((IoBuffer) message).hasRemaining()) {
+                throw new IllegalArgumentException(
+                "message is empty. Forgot to call flip()?");
+            } else if (message instanceof FileChannel) {
+                FileChannel fileChannel = (FileChannel) message;
+                message = new DefaultFileRegion(fileChannel, 0, fileChannel.size());
+            } else if (message instanceof File) {
+                File file = (File) message;
+                openedFileChannel = new FileInputStream(file).getChannel();
+                message = new DefaultFileRegion(openedFileChannel, 0, openedFileChannel.size());
             }
+        } catch (IOException e) {
+            ExceptionMonitor.getInstance().exceptionCaught(e);
+            return DefaultWriteFuture.newNotWrittenFuture(this, e);
         }
 
         WriteFuture future = new DefaultWriteFuture(this);
         getFilterChain().fireFilterWrite(
                 new DefaultWriteRequest(message, future, remoteAddress));
 
-        if (message instanceof File) {
-            final FileChannel finalChannel = channel;
+        if (openedFileChannel != null) {
+            // If we opened a FinalChannel, it needs to be closed when the write has completed
+            final FileChannel finalChannel = openedFileChannel;
             future.addListener(new IoFutureListener<WriteFuture>() {
                 public void operationComplete(WriteFuture future) {
                     try {

Modified: mina/trunk/core/src/main/java/org/apache/mina/common/AbstractPollingIoProcessor.java
URL: http://svn.apache.org/viewvc/mina/trunk/core/src/main/java/org/apache/mina/common/AbstractPollingIoProcessor.java?rev=607125&r1=607124&r2=607125&view=diff
==============================================================================
--- mina/trunk/core/src/main/java/org/apache/mina/common/AbstractPollingIoProcessor.java (original)
+++ mina/trunk/core/src/main/java/org/apache/mina/common/AbstractPollingIoProcessor.java Thu Dec 27 13:34:55 2007
@@ -591,6 +591,13 @@
             }
             localWrittenBytes = transferFile(session, region, length);
             region.setPosition(region.getPosition() + localWrittenBytes);
+            
+            // Fix for Java bug on Linux http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5103988
+            // If there's still data to be written in the FileRegion, return 0 indicating that we need
+            // to pause until writing may resume.
+            if (localWrittenBytes > 0 && region.getCount() > 0) {
+                return 0;
+            }
         } else {
             localWrittenBytes = 0;
         }

Modified: mina/trunk/core/src/main/java/org/apache/mina/transport/socket/nio/NioProcessor.java
URL: http://svn.apache.org/viewvc/mina/trunk/core/src/main/java/org/apache/mina/transport/socket/nio/NioProcessor.java?rev=607125&r1=607124&r2=607125&view=diff
==============================================================================
--- mina/trunk/core/src/main/java/org/apache/mina/transport/socket/nio/NioProcessor.java (original)
+++ mina/trunk/core/src/main/java/org/apache/mina/transport/socket/nio/NioProcessor.java Thu Dec 27 13:34:55 2007
@@ -173,7 +173,8 @@
 
     @Override
     protected int transferFile(NioSession session, FileRegion region, int length) throws Exception {
-        return (int) region.getFileChannel().transferTo(region.getPosition(), region.getCount(), session.getChannel());
+        int writtenBytes = (int) region.getFileChannel().transferTo(region.getPosition(), length, session.getChannel());
+        return writtenBytes;
     }
 
     protected static class IoSessionIterator implements Iterator<NioSession> {

Added: mina/trunk/core/src/test/java/org/apache/mina/transport/AbstractFileRegionTest.java
URL: http://svn.apache.org/viewvc/mina/trunk/core/src/test/java/org/apache/mina/transport/AbstractFileRegionTest.java?rev=607125&view=auto
==============================================================================
--- mina/trunk/core/src/test/java/org/apache/mina/transport/AbstractFileRegionTest.java (added)
+++ mina/trunk/core/src/test/java/org/apache/mina/transport/AbstractFileRegionTest.java Thu Dec 27 13:34:55 2007
@@ -0,0 +1,113 @@
+package org.apache.mina.transport;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.util.concurrent.CountDownLatch;
+
+import junit.framework.TestCase;
+
+import org.apache.mina.common.ConnectFuture;
+import org.apache.mina.common.IoAcceptor;
+import org.apache.mina.common.IoBuffer;
+import org.apache.mina.common.IoConnector;
+import org.apache.mina.common.IoHandlerAdapter;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.util.AvailablePortFinder;
+
+public abstract class AbstractFileRegionTest extends TestCase {
+
+    private static final int FILE_SIZE = 1 * 1024 * 1024; // 1MB file
+    
+    protected abstract IoAcceptor createAcceptor();
+    protected abstract IoConnector createConnector();
+
+    public void testSendLargeFile() throws Throwable {
+        File file = createLargeFile();
+        assertEquals("Test file not as big as specified", FILE_SIZE, file.length());
+        
+        final CountDownLatch latch = new CountDownLatch(1);
+        final boolean[] success = {false};
+        final Throwable[] exception = {null};
+        
+        int port = AvailablePortFinder.getNextAvailable(1025);
+        IoAcceptor acceptor = createAcceptor();
+        acceptor.setHandler(new IoHandlerAdapter() {
+            private int index = 0;
+            @Override
+            public void exceptionCaught(IoSession session, Throwable cause)
+                    throws Exception {
+                exception[0] = cause;
+                session.close();
+            }
+            @Override
+            public void sessionClosed(IoSession session) throws Exception {
+                latch.countDown();
+            }
+            @Override
+            public void messageReceived(IoSession session, Object message) throws Exception {
+                IoBuffer buffer = (IoBuffer) message;
+                while (buffer.hasRemaining()) {
+                    int x = buffer.getInt();
+                    if (x != index) {
+                        throw new Exception(String.format("Integer at %d was %d but should have been %d", index, x, index));
+                    }
+                    index++;
+                }
+                if (index > FILE_SIZE / 4) {
+                    throw new Exception("Read too much data");
+                }
+                if (index == FILE_SIZE / 4) {
+                    success[0] = true;
+                    session.close();
+                }
+            }
+        });
+        acceptor.bind(new InetSocketAddress(port));
+        
+        IoConnector connector = createConnector();
+        connector.setHandler(new IoHandlerAdapter() {
+            @Override
+            public void exceptionCaught(IoSession session, Throwable cause)
+                    throws Exception {
+                exception[0] = cause;
+                latch.countDown();
+            }
+        });
+        ConnectFuture future = connector.connect(new InetSocketAddress("localhost", port));
+        future.awaitUninterruptibly();
+        
+        future.getSession().write(file);
+        
+        latch.await();
+        
+        if (exception[0] != null) {
+            throw exception[0];
+        }
+        assertTrue("Did not complete file transfer successfully", success[0]);
+        
+        connector.dispose();
+        acceptor.dispose();
+    }
+    
+    private File createLargeFile() throws IOException {
+        File largeFile = File.createTempFile("mina-test", "largefile");
+        FileChannel channel = new FileOutputStream(largeFile).getChannel();
+        ByteBuffer buffer = createBuffer();
+        channel.write(buffer);
+        channel.close();
+        return largeFile;
+    }
+    private ByteBuffer createBuffer() {
+        ByteBuffer buffer = ByteBuffer.allocate(FILE_SIZE);
+        for (int i = 0; i < FILE_SIZE / 4; i++) {
+            buffer.putInt(i);
+        }
+        buffer.flip();
+        return buffer;
+    }
+    
+}

Propchange: mina/trunk/core/src/test/java/org/apache/mina/transport/AbstractFileRegionTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: mina/trunk/core/src/test/java/org/apache/mina/transport/socket/nio/NioFileRegionTest.java
URL: http://svn.apache.org/viewvc/mina/trunk/core/src/test/java/org/apache/mina/transport/socket/nio/NioFileRegionTest.java?rev=607125&view=auto
==============================================================================
--- mina/trunk/core/src/test/java/org/apache/mina/transport/socket/nio/NioFileRegionTest.java (added)
+++ mina/trunk/core/src/test/java/org/apache/mina/transport/socket/nio/NioFileRegionTest.java Thu Dec 27 13:34:55 2007
@@ -0,0 +1,19 @@
+package org.apache.mina.transport.socket.nio;
+
+import org.apache.mina.common.IoAcceptor;
+import org.apache.mina.common.IoConnector;
+import org.apache.mina.transport.AbstractFileRegionTest;
+
+public class NioFileRegionTest extends AbstractFileRegionTest{
+
+    @Override
+    protected IoAcceptor createAcceptor() {
+        return new NioSocketAcceptor();
+    }
+
+    @Override
+    protected IoConnector createConnector() {
+        return new NioSocketConnector();
+    }
+
+}

Propchange: mina/trunk/core/src/test/java/org/apache/mina/transport/socket/nio/NioFileRegionTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain