harmony-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From regi...@apache.org
Subject svn commit: r816508 - in /harmony/enhanced/classlib/trunk/modules: luni/src/main/java/org/apache/harmony/luni/platform/ luni/src/main/native/luni/shared/ luni/src/main/native/luni/unix/ luni/src/main/native/luni/windows/ nio/src/main/java/common/org/ap...
Date Fri, 18 Sep 2009 07:51:31 GMT
Author: regisxu
Date: Fri Sep 18 07:51:30 2009
New Revision: 816508

URL: http://svn.apache.org/viewvc?rev=816508&view=rev
Log:
Apply patch for HARMONY-6328: [classlib][nio] optimize SocketChannel.write(ByteBuffer[], int,
int) by writev

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/luni/src/main/native/luni/shared/OSNetworkSystem.h
    harmony/enhanced/classlib/trunk/modules/luni/src/main/native/luni/shared/harmonyglob.h
    harmony/enhanced/classlib/trunk/modules/luni/src/main/native/luni/shared/nethelp.c
    harmony/enhanced/classlib/trunk/modules/luni/src/main/native/luni/unix/OSNetworkSystemLinux.c
    harmony/enhanced/classlib/trunk/modules/luni/src/main/native/luni/unix/exports.txt
    harmony/enhanced/classlib/trunk/modules/luni/src/main/native/luni/windows/OSNetworkSystemWin32.c
    harmony/enhanced/classlib/trunk/modules/nio/src/main/java/common/org/apache/harmony/nio/internal/SocketChannelImpl.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?rev=816508&r1=816507&r2=816508&view=diff
==============================================================================
--- 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
Fri Sep 18 07:51:30 2009
@@ -62,6 +62,9 @@
     public int writeDirect(FileDescriptor fd, long address, int count)
             throws IOException;
 
+    public int writev(FileDescriptor fd, Object[] buffers, int[] offsets,
+            int[] counts, int length) throws IOException;
+
 	public void setNonBlocking(FileDescriptor aFD, boolean block)
 			throws IOException;
 

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?rev=816508&r1=816507&r2=816508&view=diff
==============================================================================
--- 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
Fri Sep 18 07:51:30 2009
@@ -534,4 +534,26 @@
      */
     public native int writeDirect(FileDescriptor fd, long address, int count)
             throws IOException;
+
+    /**
+     * Write given buffers to a socket. The given buffers is a Object array, the
+     * element of array must be direct buffer or a byte array to be written.
+     *
+     * @param fd
+     *            the socket on which to write the bytes
+     * @param buffers
+     *            the element of array must be direct buffer or a byte array to
+     *            be written
+     * @param offsets
+     *            the index of the first byte to be write
+     * @param counts
+     *            the maximum number of bytes to be written
+     * @param length
+     *            the size of buffer array
+     * @return the actual number of bytes written
+     * @throws IOException
+     *             if there is an underlying socket problem
+     */
+    public native int writev(FileDescriptor fd, Object[] buffers,
+            int[] offsets, int[] counts, int length) throws IOException;
 }

Modified: harmony/enhanced/classlib/trunk/modules/luni/src/main/native/luni/shared/OSNetworkSystem.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/luni/src/main/native/luni/shared/OSNetworkSystem.h?rev=816508&r1=816507&r2=816508&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/luni/src/main/native/luni/shared/OSNetworkSystem.h
(original)
+++ harmony/enhanced/classlib/trunk/modules/luni/src/main/native/luni/shared/OSNetworkSystem.h
Fri Sep 18 07:51:30 2009
@@ -466,6 +466,14 @@
 JNIEXPORT jint JNICALL Java_org_apache_harmony_luni_platform_OSNetworkSystem_writeDirect
   (JNIEnv *, jobject, jobject, jlong, jint);
 
+/*
+ * Class:     org_apache_harmony_luni_platform_OSNetworkSystem
+ * Method:    writev
+ * Signature: (Ljava/io/FileDescriptor;[Ljava/lang/Object;[I[II)I
+ */
+JNIEXPORT jint JNICALL Java_org_apache_harmony_luni_platform_OSNetworkSystem_writev
+  (JNIEnv *, jobject, jobject, jobjectArray, jintArray, jintArray, jint);
+
 #ifdef __cplusplus
 }
 #endif

Modified: harmony/enhanced/classlib/trunk/modules/luni/src/main/native/luni/shared/harmonyglob.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/luni/src/main/native/luni/shared/harmonyglob.h?rev=816508&r1=816507&r2=816508&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/luni/src/main/native/luni/shared/harmonyglob.h
(original)
+++ harmony/enhanced/classlib/trunk/modules/luni/src/main/native/luni/shared/harmonyglob.h
Fri Sep 18 07:51:30 2009
@@ -74,6 +74,7 @@
   /* additional IDs for luni and nio */
   jclass CLS_java_lang_Long;
   jclass CLS_java_net_Inet6Address;
+  jclass CLS_java_nio_DirectByteBuffer;
   jfieldID FID_java_lang_Long_value;
   jmethodID MID_java_net_InetAddress_init;
 } LUNIJniIDCache;

Modified: harmony/enhanced/classlib/trunk/modules/luni/src/main/native/luni/shared/nethelp.c
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/luni/src/main/native/luni/shared/nethelp.c?rev=816508&r1=816507&r2=816508&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/luni/src/main/native/luni/shared/nethelp.c (original)
+++ harmony/enhanced/classlib/trunk/modules/luni/src/main/native/luni/shared/nethelp.c Fri
Sep 18 07:51:30 2009
@@ -208,7 +208,14 @@
   if (!globalRef)
     return;
   HARMONY_CACHE_SET (env, CLS_java_net_Inet6Address, globalRef);
-  
+  lookupClass = (*env)->FindClass (env, "java/nio/DirectByteBuffer");
+  if (!lookupClass)
+    return;
+  globalRef = (*env)->NewGlobalRef (env, lookupClass);
+  if (!globalRef)
+    return;
+  HARMONY_CACHE_SET (env, CLS_java_nio_DirectByteBuffer, globalRef);
+
 }
 
 /**

Modified: harmony/enhanced/classlib/trunk/modules/luni/src/main/native/luni/unix/OSNetworkSystemLinux.c
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/luni/src/main/native/luni/unix/OSNetworkSystemLinux.c?rev=816508&r1=816507&r2=816508&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/luni/src/main/native/luni/unix/OSNetworkSystemLinux.c
(original)
+++ harmony/enhanced/classlib/trunk/modules/luni/src/main/native/luni/unix/OSNetworkSystemLinux.c
Fri Sep 18 07:51:30 2009
@@ -712,3 +712,82 @@
 
   return result;
 }
+
+JNIEXPORT jint JNICALL
+Java_org_apache_harmony_luni_platform_OSNetworkSystem_writev
+(JNIEnv *env, jobject thiz, jobject fd, jobjectArray buffers, jintArray offset, jintArray
counts, jint length) {
+
+  PORT_ACCESS_FROM_ENV(env);
+
+  jobject buffer;
+  jobject* toBeReleasedBuffers;
+  jint *cts;
+  jint *noffset;
+  jboolean isDirectBuffer = JNI_FALSE;
+  jint result;
+  jclass byteBufferClass;
+  struct iovec* vect;
+  int i;
+
+  hysocket_t socketP = getJavaIoFileDescriptorContentsAsAPointer(env, fd);
+
+  if (!hysock_socketIsValid(socketP)) {
+    throwJavaNetSocketException(env, HYPORT_ERROR_SOCKET_BADSOCKET);
+    return (jint) 0;
+  }
+
+  vect = (struct iovec*) hymem_allocate_memory(sizeof(struct iovec) * length);
+  if (vect == NULL) {
+    throwNewOutOfMemoryError(env, "");
+    return 0;
+  }
+
+  toBeReleasedBuffers = (jobject*) hymem_allocate_memory(sizeof(jobject) * length);
+  if (toBeReleasedBuffers == NULL) {
+    throwNewOutOfMemoryError(env, "");
+    return 0;
+  }
+
+  byteBufferClass = HARMONY_CACHE_GET (env, CLS_java_nio_DirectByteBuffer);
+  noffset = (*env)->GetIntArrayElements(env, offset, NULL);
+
+  cts = (*env)->GetPrimitiveArrayCritical(env, counts, NULL);
+
+  for (i = 0; i < length; ++i) {
+    buffer = (*env)->GetObjectArrayElement(env, buffers, i);
+    isDirectBuffer = (*env)->IsInstanceOf(env, buffer, byteBufferClass);
+    if (isDirectBuffer) {
+      vect[i].iov_base =  (U_8 *)(jbyte *)(IDATA) (*env)->GetDirectBufferAddress(env,
buffer) + noffset[i];
+      toBeReleasedBuffers[i] = NULL;
+    } else {
+      vect[i].iov_base = (U_8 *)(jbyte *)(IDATA) (*env)->GetByteArrayElements(env, buffer,
NULL) + noffset[i];
+      toBeReleasedBuffers[i] = buffer;
+    }
+    vect[i].iov_len = cts[i];
+  }
+
+  (*env)->ReleasePrimitiveArrayCritical(env, counts, cts, JNI_ABORT);
+
+  result = writev(SOCKET_CAST (socketP), vect, length);
+
+  for (i = 0; i < length; ++i) {
+    if (toBeReleasedBuffers[i] != NULL) {
+      (*env)->ReleaseByteArrayElements(env, toBeReleasedBuffers[i], vect[i].iov_base -
noffset[i], JNI_ABORT);
+    }
+  }
+
+  (*env)->ReleaseIntArrayElements(env, offset, noffset, JNI_ABORT);
+
+  hymem_free_memory(toBeReleasedBuffers);
+  hymem_free_memory(vect);
+
+  if (0 > result) {
+      if (errno == EAGAIN) {
+          return 0;
+      }
+    throwJavaNetSocketException(env, result);
+    return (jint) 0;  // Ignored, exception takes precedence
+  }
+
+  return (jint) result;
+}

Modified: harmony/enhanced/classlib/trunk/modules/luni/src/main/native/luni/unix/exports.txt
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/luni/src/main/native/luni/unix/exports.txt?rev=816508&r1=816507&r2=816508&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/luni/src/main/native/luni/unix/exports.txt (original)
+++ harmony/enhanced/classlib/trunk/modules/luni/src/main/native/luni/unix/exports.txt Fri
Sep 18 07:51:30 2009
@@ -170,6 +170,7 @@
 Java_org_apache_harmony_luni_platform_OSNetworkSystem_readDirect
 Java_org_apache_harmony_luni_platform_OSNetworkSystem_write
 Java_org_apache_harmony_luni_platform_OSNetworkSystem_writeDirect
+Java_org_apache_harmony_luni_platform_OSNetworkSystem_writev
 Java_org_apache_harmony_luni_platform_OSNetworkSystem_setNonBlocking
 Java_org_apache_harmony_luni_platform_OSNetworkSystem_connect
 Java_org_apache_harmony_luni_platform_OSNetworkSystem_connectWithTimeout

Modified: harmony/enhanced/classlib/trunk/modules/luni/src/main/native/luni/windows/OSNetworkSystemWin32.c
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/luni/src/main/native/luni/windows/OSNetworkSystemWin32.c?rev=816508&r1=816507&r2=816508&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/luni/src/main/native/luni/windows/OSNetworkSystemWin32.c
(original)
+++ harmony/enhanced/classlib/trunk/modules/luni/src/main/native/luni/windows/OSNetworkSystemWin32.c
Fri Sep 18 07:51:30 2009
@@ -434,3 +434,88 @@
   return result;
 }
 
+JNIEXPORT jint JNICALL
+Java_org_apache_harmony_luni_platform_OSNetworkSystem_writev
+  (JNIEnv *env, jobject thiz, jobject fd, jobjectArray buffers, jintArray offsets, jintArray
counts, jint length) {
+
+  PORT_ACCESS_FROM_ENV(env);
+
+  jobject buffer;
+  jobject* toBeReleasedBuffers;
+  jint *cts;
+  jint *noffset;
+  jboolean isDirectBuffer = JNI_FALSE;
+  jint result;
+  LPWSABUF vect;
+  int i;
+  jint sentBytes;
+  jint rc;
+  jclass byteBufferClass;
+
+  hysocket_t socketP = getJavaIoFileDescriptorContentsAsAPointer(env, fd);
+
+  if (!hysock_socketIsValid(socketP)) {
+    throwJavaNetSocketException(env, HYPORT_ERROR_SOCKET_BADSOCKET);
+    return (jint) 0;
+  }
+
+  vect = (LPWSABUF) hymem_allocate_memory(sizeof(WSABUF) * length);
+  if (vect == NULL) {
+    throwNewOutOfMemoryError(env, "");
+    return 0;
+  }
+
+  toBeReleasedBuffers = (jobject*) hymem_allocate_memory(sizeof(jobject) * length);
+  if (toBeReleasedBuffers == NULL) {
+    throwNewOutOfMemoryError(env, "");
+    return 0;
+  }
+
+  byteBufferClass = HARMONY_CACHE_GET (env, CLS_java_nio_DirectByteBuffer);
+  noffset = (*env)->GetIntArrayElements(env, offsets, NULL);
+
+  cts = (*env)->GetPrimitiveArrayCritical(env, counts, NULL);
+
+  for (i = 0; i < length; ++i) {
+    buffer = (*env)->GetObjectArrayElement(env, buffers, i);
+    isDirectBuffer = (*env)->IsInstanceOf(env, buffer, byteBufferClass);
+    if (isDirectBuffer) {
+      vect[i].buf =  (U_8 *)(jbyte *)(IDATA) (*env)->GetDirectBufferAddress(env, buffer)
+ noffset[i];
+      toBeReleasedBuffers[i] = NULL;
+    } else {
+      vect[i].buf = (U_8 *)(jbyte *)(IDATA) (*env)->GetByteArrayElements(env, buffer,
NULL) + noffset[i];
+      toBeReleasedBuffers[i] = buffer;
+    }
+    vect[i].len = cts[i];
+  }
+
+  (*env)->ReleasePrimitiveArrayCritical(env, counts, cts, JNI_ABORT);
+
+  if (socketP->flags & SOCKET_USE_IPV4_MASK)
+    {
+      result = WSASend(socketP->ipv4, vect, length, &sentBytes, HYSOCK_NOFLAGS, NULL,
NULL);
+    }
+  else
+    {
+      result = WSASend(socketP->ipv6, vect, length, &sentBytes, HYSOCK_NOFLAGS, NULL,
NULL);
+    }
+
+  for (i = 0; i < length; ++i) {
+    if (toBeReleasedBuffers[i] != NULL) {
+      (*env)->ReleaseByteArrayElements(env, toBeReleasedBuffers[i], vect[i].buf - noffset[i],
JNI_ABORT);
+    }
+  }
+
+  (*env)->ReleaseIntArrayElements(env, offsets, noffset, JNI_ABORT);
+
+  hymem_free_memory(toBeReleasedBuffers);
+  hymem_free_memory(vect);
+
+  if (SOCKET_ERROR == result) {
+    rc = WSAGetLastError ();
+    throwJavaNetSocketException(env, rc);
+    return (jint) 0;  // Ignored, exception takes precedence
+  }
+
+  return sentBytes;
+}

Modified: harmony/enhanced/classlib/trunk/modules/nio/src/main/java/common/org/apache/harmony/nio/internal/SocketChannelImpl.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/common/org/apache/harmony/nio/internal/SocketChannelImpl.java?rev=816508&r1=816507&r2=816508&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/nio/src/main/java/common/org/apache/harmony/nio/internal/SocketChannelImpl.java
(original)
+++ harmony/enhanced/classlib/trunk/modules/nio/src/main/java/common/org/apache/harmony/nio/internal/SocketChannelImpl.java
Fri Sep 18 07:51:30 2009
@@ -495,19 +495,39 @@
         }
 
         checkOpenConnected();
-        int count = calculateByteBufferArray(sources, offset, length);
-        if (0 == count) {
-            return 0;
+
+        Object[] src = new Object[length];
+        int[] offsets = new int[length];
+        int[] counts = new int[length];
+        for (int i = 0; i < length; ++i) {
+            ByteBuffer buffer = sources[i + offset];
+            if (!buffer.isDirect()) {
+                if (buffer.hasArray()) {
+                    src[i] = buffer.array();
+                    counts[i] = buffer.remaining();
+                    offsets[i] = buffer.position();
+                } else {
+                    ByteBuffer db = ByteBuffer.allocateDirect(buffer.remaining());
+                    int oldPosition = buffer.position();
+                    db.put(buffer);
+                    buffer.position(oldPosition);
+                    db.flip();
+                    src[i] = db;
+                    counts[i] = buffer.remaining();
+                    offsets[i] = 0;
+                }
+            } else {
+                src[i] = buffer;
+                counts[i] = buffer.remaining();
+                offsets[i] = buffer.position();
+            }
         }
-        ByteBuffer writeBuf = ByteBuffer.allocate(count);
-        for (int val = offset; val < length + offset; val++) {
-            ByteBuffer source = sources[val];
-            int oldPosition = source.position();
-            writeBuf.put(source);
-            source.position(oldPosition);
+
+        if (length == 0) {
+            return 0;
         }
-        writeBuf.flip();
-        int result = writeImpl(writeBuf);
+
+        int result = writevImpl(src, offsets, counts);
         int val = offset;
         int written = result;
         while (result > 0) {
@@ -520,6 +540,35 @@
         return written;
     }
 
+    /*
+     * Write the source. return the count of bytes written.
+     */
+    private int writevImpl(Object[] sources, int[] offsets, int[] counts) throws IOException
{
+        int writeCount = 0;
+        try {
+            if (isBlocking()) {
+                begin();
+            }
+
+            synchronized (writeLock) {
+                writeCount = networkSystem.writev(fd, sources, offsets, counts, sources.length);
+            }
+        } catch (SocketException e) {
+            if (e.getCause() instanceof ErrorCodeException) {
+                if (ERRCODE_SOCKET_NONBLOCKING_WOULD_BLOCK == ((ErrorCodeException) e
+                        .getCause()).getErrorCode()) {
+                    return writeCount;
+                }
+            }
+            throw e;
+        } finally {
+            if (isBlocking()) {
+                end(writeCount >= 0);
+            }
+        }
+        return writeCount;
+    }
+
     private int calculateByteBufferArray(ByteBuffer[] sources, int offset,
             int length) {
         int sum = 0;

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?rev=816508&r1=816507&r2=816508&view=diff
==============================================================================
--- 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
Fri Sep 18 07:51:30 2009
@@ -2657,6 +2657,32 @@
         sc.write(byteBufferArray);
         assertTrue(sc.isWriteCalled);
     }
+
+    /**
+     * @tests java.nio.channels.SocketChannel#write(ByteBuffer[])
+     */
+    public void test_writev() throws Exception {
+        ServerSocketChannel ssc = ServerSocketChannel.open();
+        ssc.socket().bind(localAddr2);
+        SocketChannel sc = SocketChannel.open();
+        sc.connect(localAddr2);
+        SocketChannel sock = ssc.accept();
+        ByteBuffer[] buf = { ByteBuffer.allocate(10), ByteBuffer.allocateDirect(20) };
+
+        while (buf[0].remaining() != 0 && buf[1].remaining() !=0) {
+            assertTrue(sc.write(buf, 0, 2) >= 0);
+        }
+
+        ByteBuffer target = ByteBuffer.allocate(30);
+
+        while (target.remaining() != 0) {
+            assertTrue(sock.read(target) >=0);
+        }
+
+        ssc.close();
+        sc.close();
+        sock.close();
+    }
     
     public void testSocket_configureblocking() throws IOException {
         byte[] serverWBuf = new byte[CAPACITY_NORMAL];



Mime
View raw message