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 {