Author: mturk
Date: Thu Aug 11 05:43:12 2011
New Revision: 1156493
URL: http://svn.apache.org/viewvc?rev=1156493&view=rev
Log:
Implement basic win32 sendfile
Modified:
commons/sandbox/runtime/trunk/src/main/native/include/acr/descriptor.h
commons/sandbox/runtime/trunk/src/main/native/os/win32/arch_opts.h
commons/sandbox/runtime/trunk/src/main/native/os/win32/exec.c
commons/sandbox/runtime/trunk/src/main/native/os/win32/inetsock.c
commons/sandbox/runtime/trunk/src/main/native/os/win32/init.c
commons/sandbox/runtime/trunk/src/main/native/os/win32/sendfile.c
commons/sandbox/runtime/trunk/src/main/native/os/win32/sockstream.c
commons/sandbox/runtime/trunk/src/main/native/os/win32/util.c
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=1156493&r1=1156492&r2=1156493&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 05:43:12 2011
@@ -92,13 +92,13 @@ struct acr_sf_t {
#else
HANDLE fh;
#endif
- off_t off;
+ acr_off_t off;
#if !defined(WINDOWS)
struct_stat_t info;
#else
LPOVERLAPPED pob; /**< For TransmitFile */
#endif
- size_t count;
+ acr_off_t size;
};
@@ -111,6 +111,13 @@ AcrGetDescriptorFd(JNI_STDARGS);
int
AcrSetDescriptorFd(JNI_STDARGS, void *fd);
+#if defined (WINDOWS)
+HANDLE
+AcrGetFileDescriptorHandle(JNI_STDARGS);
+int
+AcrSetFileDescriptorHandle(JNI_STDARGS, HANDLE fh);
+#endif
+
#ifdef __cplusplus
}
#endif
Modified: commons/sandbox/runtime/trunk/src/main/native/os/win32/arch_opts.h
URL:
http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/win32/arch_opts.h?rev=1156493&r1=1156492&r2=1156493&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/os/win32/arch_opts.h
(original)
+++ commons/sandbox/runtime/trunk/src/main/native/os/win32/arch_opts.h Thu Aug
11 05:43:12 2011
@@ -266,6 +266,22 @@ ACR_INLINE(void) MsecTimeToFileTime(LPFI
return;
}
+ACR_INLINE(acr_int64_t) AcrToInt64(DWORD hi, DWORD lo)
+{
+ LARGE_INTEGER i;
+ i.HighPart = hi;
+ i.LowPart = lo;
+ return i.QuadPart;
+}
+
+typedef struct winsock_env_t {
+ LPFN_ACCEPTEX AcceptEx;
+ LPFN_GETACCEPTEXSOCKADDRS GetAcceptExSockaddrs;
+ LPFN_TRANSMITFILE TransmitFile;
+} winsock_env_t;
+
+extern winsock_env_t *winsock;
+
HANDLE AcrNullPipe(int flags, int fd);
int AcrPipePair(HANDLE *rd, HANDLE *wr, int flags, char *name);
int AcrSocketPair(SOCKET *rd, SOCKET *wr, int nonblocking);
Modified: commons/sandbox/runtime/trunk/src/main/native/os/win32/exec.c
URL:
http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/win32/exec.c?rev=1156493&r1=1156492&r2=1156493&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/os/win32/exec.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/os/win32/exec.c Thu Aug 11
05:43:12 2011
@@ -566,7 +566,7 @@ ACR_WIN_EXPORT(jlong, WindowsExec, exec0
rv = _run_exec(J2S(executable), J2S(args), J2S(envb), J2S(cwd),
ob, eb, ib, timeout, &rc);
if (inpcopy != 0) {
- (*env)->ReleasePrimitiveArrayCritical(env, inpcopy, ib->buf, 0);
+ (*env)->ReleasePrimitiveArrayCritical(env, inpcopy, ib->buf, 0);
(*env)->DeleteLocalRef(env, inpcopy);
}
if (rv != ACR_PARENT_ERROR) {
@@ -604,5 +604,5 @@ cleanup:
} DONE_WITH_STR(args);
} DONE_WITH_STR(executable);
- return ((jlong)rv << 32) | ((jlong)rc & ACR_I64_C(0xFFFFFFFF));
+ return AcrToInt64(rv, rc);
}
Modified: commons/sandbox/runtime/trunk/src/main/native/os/win32/inetsock.c
URL:
http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/win32/inetsock.c?rev=1156493&r1=1156492&r2=1156493&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/os/win32/inetsock.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/os/win32/inetsock.c Thu Aug
11 05:43:12 2011
@@ -38,12 +38,14 @@ ACR_NET_EXPORT(jint, SocketDescriptor, c
if (fd == 0)
return ACR_EBADF;
sd = fd->s;
+#if 0
if (fd->pob != 0) {
/* Close TransmitFile overlapped struct */
SAFE_CLOSE_HANDLE(fd->pob->hEvent);
AcrFree(fd->pob);
fd->pob = 0;
}
+#endif
if (sd != INVALID_SOCKET) {
fd->s = INVALID_SOCKET;
if (fd->socketfname != 0) {
Modified: commons/sandbox/runtime/trunk/src/main/native/os/win32/init.c
URL:
http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/win32/init.c?rev=1156493&r1=1156492&r2=1156493&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/os/win32/init.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/os/win32/init.c Thu Aug 11
05:43:12 2011
@@ -32,7 +32,6 @@ HANDLE _heap_handle = 0
LPSYSTEM_INFO acr_osinf = &osinf;
LPOSVERSIONINFOEXA acr_osver = &osver;
HANDLE acr_raised_event = 0;
-HANDLE acr_alived_mutex = 0;
extern int AcrIpcInit(void);
typedef struct tlsd_t
@@ -139,6 +138,28 @@ AcrGetThreadError()
return ACR_ENOMEM;
}
+int
+AcrInitialize()
+{
+ int rc;
+ WORD wVersionRequested;
+ WSADATA wsaData;
+
+ /* Winsock should be already initialized
+ * by the JVM
+ */
+ wVersionRequested = MAKEWORD(2, 2);
+ if ((rc = WSAStartup(wVersionRequested, &wsaData)) != 0)
+ return rc;
+ GetSystemInfo(acr_osinf);
+ acr_osver->dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
+ GetVersionExA((LPOSVERSIONINFOA)acr_osver);
+ acr_raised_event = CreateEvent(0, TRUE, FALSE, 0);
+ if (IS_INVALID_HANDLE(acr_raised_event))
+ return GetLastError();
+ return rc;
+}
+
/* Called by the JVM when ACR is loaded */
ACR_API(jint)
JNI_OnLoad(JavaVM *vm, void *reserved)
@@ -154,13 +175,7 @@ JNI_OnLoad(JavaVM *vm, void *reserved)
*/
return JNI_ERR;
}
- GetSystemInfo(acr_osinf);
- acr_osver->dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
- GetVersionExA((LPOSVERSIONINFOA)acr_osver);
- acr_raised_event = CreateEvent(0, TRUE, FALSE, 0);
- acr_alived_mutex = CreateMutex(GetSaWithNullDacl(0, JNI_FALSE), TRUE, 0);
-
- if (IS_INVALID_HANDLE(acr_raised_event))
+ if (AcrInitialize() != 0)
return JNI_ERR;
if (AcrLoadLateDLLs() != 0)
return JNI_ERR;
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=1156493&r1=1156492&r2=1156493&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 05:43:12 2011
@@ -22,7 +22,199 @@
#include "acr/iodefs.h"
#include "acr/netapi.h"
#include "acr/ring.h"
+#include "acr/string.h"
#include "acr/misc.h"
#include "arch_opts.h"
#include "arch_sync.h"
+ACR_NET_EXPORT(jlong, SendFile, open0)(JNI_STDARGS, jstring fname)
+{
+ int rc = 0;
+ acr_sf_t *sf;
+ if ((sf = ACR_TALLOC(acr_sf_t)) == 0)
+ return 0;
+ WITH_WSTR(fname) {
+ sf->fh = CreateFileW(J2S(fname),
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ 0,
+ OPEN_EXISTING,
+ FILE_FLAG_SEQUENTIAL_SCAN,
+ 0);
+ if (sf->fh == INVALID_HANDLE_VALUE) {
+ rc = GetLastError();
+ }
+ else {
+ BY_HANDLE_FILE_INFORMATION fi;
+ if (GetFileInformationByHandle(sf->fh, &fi))
+ sf->size = AcrToInt64(fi.nFileSizeHigh, fi.nFileSizeLow);
+ else
+ rc = GetLastError();
+ }
+ } DONE_WITH_STR(fname);
+ 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(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;
+ acr_sf_t *sf = J2P(fp, acr_sf_t *);
+
+ CloseHandle(sf->fh);
+ CloseHandle(sf->pob->hEvent);
+ AcrFree(sf->pob);
+ AcrFree(sf);
+ return rc;
+}
+
+ACR_NET_EXPORT(jlong, Sendfile, size0)(JNI_STDARGS, jlong fp)
+{
+ acr_sf_t *sf = J2P(fp, acr_sf_t *);
+ 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;
+}
+
+#define MAX_SEGMENT_SIZE 65536
+ACR_NET_EXPORT(jint, Sendfile, send0)(JNI_STDARGS, jlong sp, jlong fp)
+{
+ int rc = 0;
+ DWORD cnt = 0;
+ acr_sd_t *sd = J2P(sp, acr_sd_t *);
+ acr_sf_t *sf = J2P(fp, acr_sf_t *);
+ DWORD dwFlags = 0;
+ SOCKET sock;
+ acr_off_t tosend;
+ int xmitted = 0;
+
+ if ((sock = AcrSdRetain(sd)) == INVALID_SOCKET) {
+ ACR_THROW_NET_ERROR(ACR_EBADF);
+ return -1;
+ }
+ if ((sf->size - sf->off) > INT_MAX)
+ tosend = INT_MAX;
+ else
+ tosend = sf->size - sf->off;
+
+ if (ACR_HASFLAG(sd, ACR_SO_WPART)) {
+ ACR_CLRFLAG(sd, ACR_SO_WPART);
+ /* Wait for the previous operation to finish */
+ rc = AcrWaitIO(sock, sd->timeout, POLLOUT);
+ }
+ sf->pob->Offset = (DWORD)(sf->off);
+ sf->pob->OffsetHigh = (DWORD)(sf->off >> 32);
+ while (tosend > 0) {
+ if (tosend > MAX_SEGMENT_SIZE)
+ cnt = MAX_SEGMENT_SIZE;
+ else
+ cnt = (DWORD)tosend; /* Last call to TransmitFile() */
+ /* XXX: MSDN says that it should be obtained by WSAIoctl
+ * but it seems this works just fine as it is.
+ */
+ if (!(*winsock->TransmitFile)(sock, /* socket */
+ sf->fh, /* file descriptor of the file to
be sent */
+ cnt, /* number of bytes to send. 0=send
all */
+ 0, /* Number of bytes per send. 0=use
default */
+ sf->pob, /* OVERLAPPED structure */
+ 0, /* header and trailer buffers */
+ dwFlags)) { /* flags to control various
aspects of TransmitFile */
+ rc = WSAGetLastError();
+ if (rc == ERROR_IO_PENDING || rc == WSA_IO_PENDING) {
+ DWORD ws = WaitForSingleObject(sf->pob->hEvent, sd->timeout);
+ if (ws == WAIT_OBJECT_0) {
+ rc = 0;
+ if (!WSAGetOverlappedResult(sock,
+ sf->pob->hEvent,
+ &cnt,
+ FALSE,
+ &dwFlags))
+ rc = WSAGetLastError();
+ }
+ else if (ws == WAIT_TIMEOUT)
+ rc = ACR_TIMEUP;
+ else
+ rc = GetLastError();
+ }
+ }
+ if (rc != 0)
+ break;
+ tosend -= cnt;
+ sf->off += cnt;
+ xmitted += cnt;
+ }
+ if (rc != 0) {
+ xmitted = -1;
+ ACR_THROW_NET_ERROR(rc);
+ }
+ AcrSdRelease(sd);
+ return xmitted;
+}
Modified: commons/sandbox/runtime/trunk/src/main/native/os/win32/sockstream.c
URL:
http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/win32/sockstream.c?rev=1156493&r1=1156492&r2=1156493&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/os/win32/sockstream.c
(original)
+++ commons/sandbox/runtime/trunk/src/main/native/os/win32/sockstream.c Thu Aug
11 05:43:12 2011
@@ -550,6 +550,7 @@ ACR_NET_EXPORT(jlong, SocketStream, writ
{
int i;
DWORD wr = 0;
+ DWORD sz = 0;
int rc = 0;
SOCKET sd;
jbyteArray *boa = 0;
@@ -594,6 +595,7 @@ ACR_NET_EXPORT(jlong, SocketStream, writ
}
iov[i].len = (u_long)(*env)->GetArrayLength(env, boa[i]);
iov[i].buf = (char *)(*env)->GetByteArrayElements(env, boa[i], 0);
+ sz += iov[i].len;
}
if (ACR_HASFLAG(ss->fd, ACR_SO_WPART)) {
ACR_CLRFLAG(ss->fd, ACR_SO_WPART);
@@ -609,7 +611,7 @@ waitio:
if (WSASend(sd, iov, len, &wr, 0, 0, 0) == SOCKET_ERROR)
rc = WSAGetLastError();
}
- if (rc == 0 && ss->fd->timeout > 0 && wr < len)
+ if (rc == 0 && ss->fd->timeout > 0 && wr < sz)
ss->fd->flags |= ACR_SO_WPART;
finally:
sdrelease(ss);
@@ -639,6 +641,7 @@ ACR_NET_EXPORT(jlong, SocketStream, writ
{
int i;
DWORD wr = 0;
+ DWORD sz = 0;
int rc = 0;
SOCKET sd;
LPWSABUF iov = 0;
@@ -671,7 +674,7 @@ ACR_NET_EXPORT(jlong, SocketStream, writ
}
iov[i].len = (u_long)(*env)->GetDirectBufferCapacity(env, bb);
iov[i].buf = (char *)(*env)->GetDirectBufferAddress(env, bb);
-
+ sz += iov[i].len;
(*env)->DeleteLocalRef(env, bb);
}
if (ACR_HASFLAG(ss->fd, ACR_SO_WPART)) {
@@ -688,7 +691,7 @@ waitio:
if (WSASend(sd, iov, len, &wr, 0, 0, 0) == SOCKET_ERROR)
rc = WSAGetLastError();
}
- if (rc == 0 && ss->fd->timeout > 0 && wr < len)
+ if (rc == 0 && ss->fd->timeout > 0 && wr < sz)
ss->fd->flags |= ACR_SO_WPART;
finally:
sdrelease(ss);
Modified: commons/sandbox/runtime/trunk/src/main/native/os/win32/util.c
URL:
http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/win32/util.c?rev=1156493&r1=1156492&r2=1156493&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/os/win32/util.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/os/win32/util.c Thu Aug 11
05:43:12 2011
@@ -50,6 +50,9 @@ static HMODULE _opt_libinst[SYSDLL_DEFIN
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
+static winsock_env_t winsock_s = { AcceptEx, GetAcceptExSockaddrs,
TransmitFile };
+winsock_env_t *winsock = &winsock_s;
+
HMODULE
AcrGetLateDLL(SYSDLL_TOKEN libidx)
{
@@ -114,6 +117,12 @@ int
AcrLoadLateDLLs()
{
SYSDLL_TOKEN idx = SYSDLL_KERNEL32;
+ GUID id0 = WSAID_ACCEPTEX;
+ GUID id1 = WSAID_GETACCEPTEXSOCKADDRS;
+ GUID id2 = WSAID_TRANSMITFILE;
+ SOCKET sd;
+ int rc = 0;
+ DWORD bytes;
for (idx = SYSDLL_KERNEL32; idx < SYSDLL_DEFINED; idx++) {
if (AcrGetLateDLL(idx) == 0 && (idx < SYSDLL_JVM)) {
@@ -124,7 +133,32 @@ AcrLoadLateDLLs()
return GetLastError();
}
}
+ /* Load winsock pointers */
+ sd = socket(AF_INET, SOCK_STREAM, 0);
+ if (sd == INVALID_SOCKET)
+ return WSAGetLastError();
+ if (WSAIoctl(sd, SIO_GET_EXTENSION_FUNCTION_POINTER,
+ &id0, sizeof(id0),
+ &winsock_s.AcceptEx, sizeof(&winsock_s.AcceptEx),
+ &bytes, 0, 0) == SOCKET_ERROR)
+ goto failed;
+ if (WSAIoctl(sd, SIO_GET_EXTENSION_FUNCTION_POINTER,
+ &id1, sizeof(id1),
+ &winsock_s.GetAcceptExSockaddrs,
sizeof(&winsock_s.GetAcceptExSockaddrs),
+ &bytes, 0, 0) == SOCKET_ERROR)
+ goto failed;
+ if (WSAIoctl(sd, SIO_GET_EXTENSION_FUNCTION_POINTER,
+ &id2, sizeof(id2),
+ &winsock_s.TransmitFile, sizeof(&winsock_s.TransmitFile),
+ &bytes, 0, 0) == SOCKET_ERROR)
+ goto failed;
+ closesocket(sd);
return 0;
+
+failed:
+ rc = WSAGetLastError();
+ closesocket(sd);
+ return rc;
}
/* Similar to posix dup3 but it only actually works for