Author: mturk
Date: Thu Aug 11 11:23:54 2011
New Revision: 1156578

URL: http://svn.apache.org/viewvc?rev=1156578&view=rev
Log:
Add java sendfile api

Added:
    
commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/Sendfile.java
   (with props)
Modified:
    commons/sandbox/runtime/trunk/src/main/native/include/acr/descriptor.h
    commons/sandbox/runtime/trunk/src/main/native/os/linux/sendfile.c
    commons/sandbox/runtime/trunk/src/main/native/os/unix/sendfile.c
    commons/sandbox/runtime/trunk/src/main/native/os/win32/sendfile.c
    
commons/sandbox/runtime/trunk/src/main/test/org/apache/commons/runtime/TestLocalEndpoint.java

Added: 
commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/Sendfile.java
URL: 
http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/Sendfile.java?rev=1156578&view=auto
==============================================================================
--- 
commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/Sendfile.java
 (added)
+++ 
commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/Sendfile.java
 Thu Aug 11 11:23:54 2011
@@ -0,0 +1,164 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.runtime.net;
+
+import java.io.Closeable;
+import java.io.Flushable;
+import java.io.IOException;
+import java.io.SyncFailedException;
+import java.io.File;
+import java.net.SocketException;
+import org.apache.commons.runtime.io.ClosedDescriptorException;
+import org.apache.commons.runtime.io.Descriptor;
+import org.apache.commons.runtime.io.Stream;
+import org.apache.commons.runtime.OperationNotImplementedException;
+import org.apache.commons.runtime.OverflowException;
+
+/**
+ * This class represents a sendfile object.
+ */
+public class Sendfile implements Closeable
+{
+    private long        sf;
+    private boolean     closed = true;
+
+    private static native long   open0(String path)
+        throws IOException;
+    private static native int    close0(long sf);
+    private static native int    send0(long sd, long sf)
+        throws IOException;
+    private static native long   size0(long sf);
+    private static native long   size1(long sf);
+    private static native long   size2(long sf);
+    
+    private Sendfile()
+    {
+        // No instance
+    }
+
+    /**
+     * Creates a new Sendfile object.
+     */
+    public Sendfile(String path)
+        throws IOException
+    {
+        sf = open0(path);
+        closed = false;
+    }
+
+    /**
+     * Creates a new Sendfile object.
+     */
+    public Sendfile(File path)
+        throws IOException
+    {
+        sf = open0(path.getPath());
+        closed = false;
+    }
+
+    /**
+     * Free the allocated resource by the Operating system.
+     * <p>
+     * Note that {@code Object.finalize()} method will call
+     * this function. However if the native code can block for
+     * long time explicit {@code close()} should be called.
+     * </p>
+     * @see java.io.Closeable#close()
+     * @throws IOException if an I/O error occurs.
+     */
+    @Override
+    public void close()
+        throws IOException
+    {
+        if (!closed) {
+            closed = true;
+            int rc = close0(sf);
+            sf = 0L;
+        }
+    }
+
+    /**
+     * Returns whether this sendfile object is closed.
+     *
+     * @return {@code true} if the sendfile is closed,
+     *         {@code false} otherwise.
+     */
+    public boolean closed()
+    {
+        return closed;
+    }
+
+    /**
+     * Send file.
+     * The function sends file data and returns the number of bytes
+     * actually send. User should call this function untill it returns
+     * {@code zero}.
+     *
+     * @return number of bytes send or {@code -1} if the
+     *         entire file was send.
+     * @throws IOException in case of error.
+     */
+    public int send(Endpoint endpoint)
+        throws IOException
+    {
+        if (endpoint.closed() || closed)
+            throw new ClosedDescriptorException();
+        return send0(endpoint.descriptor().fd(), sf);
+    }
+
+    /**
+     * Get the size of the file to send.
+     *
+     * @return number of bytes that equals to opened file size.
+     */
+    public long length()
+        throws IOException
+    {
+        if (closed)
+            throw new ClosedDescriptorException();
+        return size0(sf);
+    }
+
+    /**
+     * Returns the number of bytes send so far.
+     *
+     * @return number of bytes send so far.
+     */
+    public long position()
+        throws IOException
+    {
+        if (closed)
+            throw new ClosedDescriptorException();
+        return size1(sf);
+    }
+
+    /**
+     * Returns the number of bytes to be send.
+     *
+     * @return number of bytes that has to be send.
+     */
+    public long remaining()
+        throws IOException
+    {
+        if (closed)
+            throw new ClosedDescriptorException();
+        return size2(sf);
+    }
+    
+}

Propchange: 
commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/Sendfile.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: commons/sandbox/runtime/trunk/src/main/native/include/acr/descriptor.h
URL: 
http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/include/acr/descriptor.h?rev=1156578&r1=1156577&r2=1156578&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/include/acr/descriptor.h 
(original)
+++ commons/sandbox/runtime/trunk/src/main/native/include/acr/descriptor.h Thu 
Aug 11 11:23:54 2011
@@ -92,13 +92,14 @@ struct acr_sf_t {
 #else
     HANDLE        fh;
 #endif
-    acr_off_t     off;
 #if !defined(WINDOWS)
-    struct_stat_t info;
+    off_t         off;
+    off_t         size;
 #else
+    acr_off_t     off;
+    acr_off_t     size;
     LPOVERLAPPED  pob;        /**< For TransmitFile       */
 #endif
-    acr_off_t     size;
 };
 
 

Modified: commons/sandbox/runtime/trunk/src/main/native/os/linux/sendfile.c
URL: 
http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/linux/sendfile.c?rev=1156578&r1=1156577&r2=1156578&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/os/linux/sendfile.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/os/linux/sendfile.c Thu Aug 
11 11:23:54 2011
@@ -48,19 +48,23 @@ ACR_NET_EXPORT(jint, Sendfile, send0)(JN
         ACR_THROW_NET_ERROR(ACR_EBADF);
         return -1;
     }
-    if (sf->info.st_size != 0) {
-        if ((sf->info.st_size - sf->off) > INT_MAX)
+    if (sf->size != 0) {
+        if ((sf->size - sf->off) > INT_MAX)
             cnt = INT_MAX;
         else
-            cnt = sf->info.st_size - sf->off;
+            cnt = sf->size - sf->off;
     }
     if (ACR_HASFLAG(sd, ACR_SO_WPART)) {
         ACR_CLRFLAG(sd, ACR_SO_WPART);
         rc = AcrWaitIO(sock, sd->timeout, POLLOUT);
+        if (rc != 0)
+            goto finally;
+    }
+    if (cnt == 0) {
+        AcrSdRelease(sd);
+        return -1;
     }
     while (rc == 0) {
-        if (cnt == 0)
-            break;
         wr = sendfile(sock,     /* socket */
                       sf->fd,   /* file descriptor of the file to be sent */
                       &sf->off, /* where in the file to start */
@@ -76,6 +80,7 @@ ACR_NET_EXPORT(jint, Sendfile, send0)(JN
             break;
         }
     }
+finally:
     if (rc != 0) {
         wr = -1;
         ACR_THROW_NET_ERROR(rc);

Modified: commons/sandbox/runtime/trunk/src/main/native/os/unix/sendfile.c
URL: 
http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/unix/sendfile.c?rev=1156578&r1=1156577&r2=1156578&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/os/unix/sendfile.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/os/unix/sendfile.c Thu Aug 11 
11:23:54 2011
@@ -17,7 +17,6 @@
 #include "acr/jnitypes.h"
 #include "acr/error.h"
 #include "acr/debug.h"
-#include "acr/iofd.h"
 #include "acr/memory.h"
 #include "acr/netapi.h"
 #include "acr/string.h"
@@ -31,6 +30,7 @@ ACR_NET_EXPORT(jlong, Sendfile, open0)(J
 {
     int       rc = 0;
     acr_sf_t *sf;
+    struct_stat_t info;
 
     if ((sf = ACR_TALLOC(acr_sf_t)) == 0)
         return 0;
@@ -49,8 +49,10 @@ ACR_NET_EXPORT(jlong, Sendfile, open0)(J
             if ((rc = AcrCloseOnExec(sf->fd, 1)) == 0)
 #endif
             {
-                if (fstat(sf->fd, &sf->info) != 0)
+                if (fstat(sf->fd, &info) == -1)
                     rc = errno;
+                else
+                    sf->size = info.st_size;
             }
         }
     } DONE_WITH_STR(fname);
@@ -63,54 +65,6 @@ ACR_NET_EXPORT(jlong, Sendfile, open0)(J
     return P2J(sf);
 }
 
-ACR_NET_EXPORT(jlong, Sendfile, open1)(JNI_STDARGS, jobject fd)
-{
-    int       rc = 0;
-    int       nd;
-    acr_sf_t *sf;
-
-    if (fd == 0) {
-        ACR_THROW_NET_ERROR(ACR_EBADF);
-        return 0;
-    }
-    nd = AcrGetFileDescriptorFd(env, fd);
-    if (nd == -1) {
-        ACR_THROW_NET_ERROR(ACR_EIO);
-        return 0;
-    }
-    if ((sf = ACR_TALLOC(acr_sf_t)) == 0)
-        return 0;
-    /* Duplicate FileDescriptor so
-     * we don't have to reference it
-     */
-#if HAVE_DUP3
-    sf->fd = dup3(nd, -1, O_CLOEXEC);
-#else
-    sf->fd = dup2(nd, -1);
-    if (sf->fd != -1) {
-        rc = AcrCloseOnExec(sf->fd, 1);
-        if (rc != 0) {
-            r_close(sf->fd);
-            errno  = rc;
-            sf->fd = -1;
-        }
-    }
-#endif
-    if (sf->fd == -1) {
-        ACR_THROW_NET_ERRNO();
-        AcrFree(sf);
-        return 0;
-    }
-    if (fstat(sf->fd, &sf->info) != 0) {
-        rc = ACR_GET_OS_ERROR();
-        r_close(sf->fd);
-        AcrFree(sf);
-        ACR_THROW_NET_ERROR(rc);
-        return 0;
-    }
-    return P2J(sf);
-}
-
 ACR_NET_EXPORT(jint, Sendfile, close0)(JNI_STDARGS, jlong fp)
 {
     int       rc = 0;
@@ -124,13 +78,17 @@ ACR_NET_EXPORT(jint, Sendfile, close0)(J
 ACR_NET_EXPORT(jlong, Sendfile, size0)(JNI_STDARGS, jlong fp)
 {
     acr_sf_t *sf = J2P(fp, acr_sf_t *);
-
-    return (jlong)sf->info.st_size;
+    return (jlong)sf->size;
 }
 
 ACR_NET_EXPORT(jlong, Sendfile, size1)(JNI_STDARGS, jlong fp)
 {
     acr_sf_t *sf = J2P(fp, acr_sf_t *);
-
     return (jlong)sf->off;
 }
+
+ACR_NET_EXPORT(jlong, Sendfile, size2)(JNI_STDARGS, jlong fp)
+{
+    acr_sf_t *sf = J2P(fp, acr_sf_t *);
+    return (jlong)(sf->size - sf->off);
+}

Modified: commons/sandbox/runtime/trunk/src/main/native/os/win32/sendfile.c
URL: 
http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/win32/sendfile.c?rev=1156578&r1=1156577&r2=1156578&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/os/win32/sendfile.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/os/win32/sendfile.c Thu Aug 
11 11:23:54 2011
@@ -70,56 +70,6 @@ ACR_NET_EXPORT(jlong, SendFile, open0)(J
     }
 }
 
-ACR_NET_EXPORT(jlong, SendFile, open1)(JNI_STDARGS, jobject fd)
-{
-    int       rc = 0;
-    HANDLE    nd;
-    acr_sf_t *sf;
-
-    if (fd == 0) {
-        ACR_THROW_NET_ERROR(ACR_EBADF);
-        return 0;
-    }
-    nd = AcrGetFileDescriptorHandle(env, fd);
-    if (IS_INVALID_HANDLE(nd)) {
-        ACR_THROW_NET_ERROR(ACR_EIO);
-        return 0;
-    }
-    if ((sf = ACR_TALLOC(acr_sf_t)) == 0)
-        return 0;
-    /* Duplicate FileDescriptor so
-     * we don't have to reference it
-     */
-    if (!DuplicateHandle(GetCurrentProcess(), nd,
-                         GetCurrentProcess(), &sf->fh,
-                         0, FALSE, DUPLICATE_SAME_ACCESS)) {
-        rc = GetLastError();
-    }
-    else {
-        BY_HANDLE_FILE_INFORMATION fi;
-        if (GetFileInformationByHandle(sf->fh, &fi))
-            sf->size = AcrToInt64(fi.nFileSizeHigh, fi.nFileSizeLow);
-        else
-            rc = GetLastError();
-    }
-    if (rc != 0) {
-        SAFE_CLOSE_HANDLE(sf->fh);
-        AcrFree(sf);
-        ACR_THROW_NET_ERROR(rc);
-        return 0;
-    }
-    sf->pob = ACR_TALLOC(OVERLAPPED);
-    if (sf->pob != 0) {
-        sf->pob->hEvent = CreateEvent(0, FALSE, FALSE, 0);
-        return P2J(sf);
-    }
-    else {
-        CloseHandle(sf->fh);
-        AcrFree(sf);
-        return 0;
-    }
-}
-
 ACR_NET_EXPORT(jint, SendFile, close0)(JNI_STDARGS, jlong fp)
 {
     int       rc = 0;
@@ -144,6 +94,12 @@ ACR_NET_EXPORT(jlong, Sendfile, size1)(J
     return (jlong)sf->off;
 }
 
+ACR_NET_EXPORT(jlong, Sendfile, size2)(JNI_STDARGS, jlong fp)
+{
+    acr_sf_t *sf = J2P(fp, acr_sf_t *);
+    return (jlong)(sf->size - sf->off);
+}
+
 #define MAX_SEGMENT_SIZE 65536
 ACR_NET_EXPORT(jint, Sendfile, send0)(JNI_STDARGS, jlong sp, jlong fp)
 {
@@ -169,6 +125,12 @@ ACR_NET_EXPORT(jint, Sendfile, send0)(JN
         ACR_CLRFLAG(sd, ACR_SO_WPART);
         /* Wait for the previous operation to finish */
         rc = AcrWaitIO(sock, sd->timeout, POLLOUT);
+        if (rc != 0)
+            goto finally;
+    }
+    if (tosend == 0) {
+        AcrSdRelease(sd);
+        return -1;
     }
     sf->pob->Offset     = (DWORD)(sf->off);
     sf->pob->OffsetHigh = (DWORD)(sf->off >> 32);
@@ -211,6 +173,7 @@ ACR_NET_EXPORT(jint, Sendfile, send0)(JN
         sf->off += cnt;
         xmitted += cnt;
     }
+finally:
     if (rc != 0) {
         xmitted = -1;
         ACR_THROW_NET_ERROR(rc);

Modified: 
commons/sandbox/runtime/trunk/src/main/test/org/apache/commons/runtime/TestLocalEndpoint.java
URL: 
http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/test/org/apache/commons/runtime/TestLocalEndpoint.java?rev=1156578&r1=1156577&r2=1156578&view=diff
==============================================================================
--- 
commons/sandbox/runtime/trunk/src/main/test/org/apache/commons/runtime/TestLocalEndpoint.java
 (original)
+++ 
commons/sandbox/runtime/trunk/src/main/test/org/apache/commons/runtime/TestLocalEndpoint.java
 Thu Aug 11 11:23:54 2011
@@ -17,6 +17,8 @@
 package org.apache.commons.runtime.net;
 
 import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileOutputStream;
 import java.io.IOException;
 import java.util.List;
 import org.testng.annotations.*;
@@ -132,7 +134,7 @@ public class TestLocalEndpoint extends A
                 //
                 sync.wait();
             }
-            Thread.sleep(100);
+            Thread.sleep(200);
         } catch (InterruptedException x) {
             // Ignore
         }
@@ -143,6 +145,24 @@ public class TestLocalEndpoint extends A
         LocalEndpoint cs = new LocalEndpoint();
         cs.connect(sa);
         assertTrue(cs.isBlocking());
+        File sendf = new File("acrsendfile.tmp");
+        sendf.deleteOnExit();
+        FileOutputStream fs = new FileOutputStream(sendf);
+        byte[] b = new byte[1000];
+        for (int i = 0; i < 500; i++)
+            fs.write(b);
+        fs.close();
+        try {
+            Sendfile sf = new Sendfile(sendf);
+            cs.configureBlocking(false);
+            int send = sf.send(cs);
+            assertTrue(send > 0);
+            assertEquals(sf.length() - send, sf.remaining());
+            cs.configureBlocking(true);
+            System.out.println("Send " + send + " bytes.");
+        } catch (Exception se) {
+            System.out.println("Error sending file " + se);
+        }
         cs.close();
         ps.interrupt();
         try {


Reply via email to