You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2014/05/23 10:58:54 UTC
svn commit: r1597034 - in /httpcomponents/httpasyncclient/branches/4.0.x: ./
httpasyncclient/src/main/java/org/apache/http/impl/nio/conn/
httpasyncclient/src/test/java/org/apache/http/impl/nio/conn/
Author: olegk
Date: Fri May 23 08:58:53 2014
New Revision: 1597034
URL: http://svn.apache.org/r1597034
Log:
Replaced dynamic proxies with custom proxy classes to reduce thread contention
Modified:
httpcomponents/httpasyncclient/branches/4.0.x/RELEASE_NOTES.txt
httpcomponents/httpasyncclient/branches/4.0.x/httpasyncclient/src/main/java/org/apache/http/impl/nio/conn/CPoolProxy.java
httpcomponents/httpasyncclient/branches/4.0.x/httpasyncclient/src/test/java/org/apache/http/impl/nio/conn/TestPoolingHttpClientAsyncConnectionManager.java
Modified: httpcomponents/httpasyncclient/branches/4.0.x/RELEASE_NOTES.txt
URL: http://svn.apache.org/viewvc/httpcomponents/httpasyncclient/branches/4.0.x/RELEASE_NOTES.txt?rev=1597034&r1=1597033&r2=1597034&view=diff
==============================================================================
--- httpcomponents/httpasyncclient/branches/4.0.x/RELEASE_NOTES.txt (original)
+++ httpcomponents/httpasyncclient/branches/4.0.x/RELEASE_NOTES.txt Fri May 23 08:58:53 2014
@@ -1,6 +1,9 @@
Changes since 4.0.1
-------------------
+* Replaced dynamic proxies with custom proxy classes to reduce thread contention.
+ Contributed by Oleg Kalnichevski <olegk at apache.org>
+
* [HTTPASYNC-73] Original request headers are not copied upon redirect
Contributed by Oleg Kalnichevski <olegk at apache.org>
Modified: httpcomponents/httpasyncclient/branches/4.0.x/httpasyncclient/src/main/java/org/apache/http/impl/nio/conn/CPoolProxy.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpasyncclient/branches/4.0.x/httpasyncclient/src/main/java/org/apache/http/impl/nio/conn/CPoolProxy.java?rev=1597034&r1=1597033&r2=1597034&view=diff
==============================================================================
--- httpcomponents/httpasyncclient/branches/4.0.x/httpasyncclient/src/main/java/org/apache/http/impl/nio/conn/CPoolProxy.java (original)
+++ httpcomponents/httpasyncclient/branches/4.0.x/httpasyncclient/src/main/java/org/apache/http/impl/nio/conn/CPoolProxy.java Fri May 23 08:58:53 2014
@@ -27,37 +27,23 @@
package org.apache.http.impl.nio.conn;
import java.io.IOException;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
+import java.net.InetAddress;
-import org.apache.http.HttpConnection;
+import javax.net.ssl.SSLSession;
+
+import org.apache.http.HttpConnectionMetrics;
+import org.apache.http.HttpException;
+import org.apache.http.HttpRequest;
+import org.apache.http.HttpResponse;
import org.apache.http.annotation.NotThreadSafe;
import org.apache.http.impl.conn.ConnectionShutdownException;
-import org.apache.http.nio.IOControl;
import org.apache.http.nio.NHttpClientConnection;
import org.apache.http.nio.conn.ManagedNHttpClientConnection;
-import org.apache.http.util.Asserts;
+import org.apache.http.nio.reactor.IOSession;
+import org.apache.http.protocol.HttpContext;
@NotThreadSafe
-class CPoolProxy implements InvocationHandler {
-
- private static final Method CLOSE_METHOD;
- private static final Method SHUTDOWN_METHOD;
- private static final Method IS_OPEN_METHOD;
- private static final Method IS_STALE_METHOD;
-
- static {
- try {
- CLOSE_METHOD = HttpConnection.class.getMethod("close");
- SHUTDOWN_METHOD = HttpConnection.class.getMethod("shutdown");
- IS_OPEN_METHOD = HttpConnection.class.getMethod("isOpen");
- IS_STALE_METHOD = HttpConnection.class.getMethod("isStale");
- } catch (final NoSuchMethodException ex) {
- throw new Error(ex);
- }
- }
+class CPoolProxy implements ManagedNHttpClientConnection {
private volatile CPoolEntry poolEntry;
@@ -76,7 +62,7 @@ class CPoolProxy implements InvocationHa
return local;
}
- NHttpClientConnection getConnection() {
+ ManagedNHttpClientConnection getConnection() {
final CPoolEntry local = this.poolEntry;
if (local == null) {
return null;
@@ -84,6 +70,15 @@ class CPoolProxy implements InvocationHa
return local.getConnection();
}
+ ManagedNHttpClientConnection getValidConnection() {
+ final ManagedNHttpClientConnection conn = getConnection();
+ if (conn == null) {
+ throw new ConnectionShutdownException();
+ }
+ return conn;
+ }
+
+ @Override
public void close() throws IOException {
final CPoolEntry local = this.poolEntry;
if (local != null) {
@@ -91,6 +86,7 @@ class CPoolProxy implements InvocationHa
}
}
+ @Override
public void shutdown() throws IOException {
final CPoolEntry local = this.poolEntry;
if (local != null) {
@@ -98,6 +94,64 @@ class CPoolProxy implements InvocationHa
}
}
+ @Override
+ public HttpConnectionMetrics getMetrics() {
+ return getValidConnection().getMetrics();
+ }
+
+ @Override
+ public void requestInput() {
+ final NHttpClientConnection conn = getConnection();
+ if (conn != null) {
+ conn.requestInput();
+ }
+ }
+
+ @Override
+ public void suspendInput() {
+ final NHttpClientConnection conn = getConnection();
+ if (conn != null) {
+ conn.suspendInput();
+ }
+ }
+
+ @Override
+ public void requestOutput() {
+ final NHttpClientConnection conn = getConnection();
+ if (conn != null) {
+ conn.requestOutput();
+ }
+ }
+
+ @Override
+ public void suspendOutput() {
+ final NHttpClientConnection conn = getConnection();
+ if (conn != null) {
+ conn.suspendOutput();
+ }
+ }
+
+ @Override
+ public InetAddress getLocalAddress() {
+ return getValidConnection().getLocalAddress();
+ }
+
+ @Override
+ public int getLocalPort() {
+ return getValidConnection().getLocalPort();
+ }
+
+ @Override
+ public InetAddress getRemoteAddress() {
+ return getValidConnection().getRemoteAddress();
+ }
+
+ @Override
+ public int getRemotePort() {
+ return getValidConnection().getRemotePort();
+ }
+
+ @Override
public boolean isOpen() {
final CPoolEntry local = this.poolEntry;
if (local != null) {
@@ -107,6 +161,7 @@ class CPoolProxy implements InvocationHa
}
}
+ @Override
public boolean isStale() {
final NHttpClientConnection conn = getConnection();
if (conn != null) {
@@ -116,59 +171,69 @@ class CPoolProxy implements InvocationHa
}
}
- public Object invoke(
- final Object proxy, final Method method, final Object[] args) throws Throwable {
- if (method.equals(CLOSE_METHOD)) {
- close();
- return null;
- } else if (method.equals(SHUTDOWN_METHOD)) {
- shutdown();
- return null;
- } else if (method.equals(IS_OPEN_METHOD)) {
- return Boolean.valueOf(isOpen());
- } else if (method.equals(IS_STALE_METHOD)) {
- return Boolean.valueOf(isStale());
- } else {
- final NHttpClientConnection conn = getConnection();
- if (conn == null) {
- if (method.getDeclaringClass().equals(IOControl.class)) {
- // Ignore IOControl operations on closed connections
- return null;
- } else {
- throw new ConnectionShutdownException();
- }
- }
- try {
- return method.invoke(conn, args);
- } catch (final InvocationTargetException ex) {
- final Throwable cause = ex.getCause();
- if (cause != null) {
- throw cause;
- } else {
- throw ex;
- }
- }
- }
+ @Override
+ public void setSocketTimeout(final int i) {
+ getValidConnection().setSocketTimeout(i);
+ }
+
+ @Override
+ public int getSocketTimeout() {
+ return getValidConnection().getSocketTimeout();
+ }
+
+ @Override
+ public void submitRequest(final HttpRequest request) throws IOException, HttpException {
+ getValidConnection().submitRequest(request);
+ }
+
+ @Override
+ public boolean isRequestSubmitted() {
+ return getValidConnection().isRequestSubmitted();
+ }
+
+ @Override
+ public void resetOutput() {
+ getValidConnection().resetOutput();
+ }
+
+ @Override
+ public void resetInput() {
+ getValidConnection().resetInput();
+ }
+
+ @Override
+ public int getStatus() {
+ return getValidConnection().getStatus();
+ }
+
+ @Override
+ public HttpRequest getHttpRequest() {
+ return getValidConnection().getHttpRequest();
+ }
+
+ @Override
+ public HttpResponse getHttpResponse() {
+ return getValidConnection().getHttpResponse();
+ }
+
+ @Override
+ public HttpContext getContext() {
+ return getValidConnection().getContext();
+ }
+
+ public static NHttpClientConnection newProxy(final CPoolEntry poolEntry) {
+ return new CPoolProxy(poolEntry);
}
- public static NHttpClientConnection newProxy(
- final CPoolEntry poolEntry) {
- return (NHttpClientConnection) Proxy.newProxyInstance(
- CPoolProxy.class.getClassLoader(),
- new Class<?>[] { ManagedNHttpClientConnection.class },
- new CPoolProxy(poolEntry));
- }
-
- private static CPoolProxy getHandler(
- final NHttpClientConnection proxy) {
- final InvocationHandler handler = Proxy.getInvocationHandler(proxy);
- Asserts.check(CPoolProxy.class.isInstance(handler),
- "Unexpected proxy handler class: %s", handler.getClass());
- return CPoolProxy.class.cast(handler);
+ private static CPoolProxy getProxy(final NHttpClientConnection conn) {
+ if (!CPoolProxy.class.isInstance(conn)) {
+ throw new IllegalStateException("Unexpected connection proxy class: " + conn.getClass());
+ }
+ return CPoolProxy.class.cast(conn);
}
public static CPoolEntry getPoolEntry(final NHttpClientConnection proxy) {
- final CPoolEntry entry = getHandler(proxy).getPoolEntry();
+ final CPoolEntry entry = getProxy(proxy).getPoolEntry();
if (entry == null) {
throw new ConnectionShutdownException();
}
@@ -176,7 +241,40 @@ class CPoolProxy implements InvocationHa
}
public static CPoolEntry detach(final NHttpClientConnection proxy) {
- return getHandler(proxy).detach();
+ return getProxy(proxy).detach();
+ }
+
+ @Override
+ public String getId() {
+ return getValidConnection().getId();
+ }
+
+ @Override
+ public void bind(final IOSession iosession) {
+ getValidConnection().bind(iosession);
+ }
+
+ @Override
+ public IOSession getIOSession() {
+ return getValidConnection().getIOSession();
+ }
+
+ @Override
+ public SSLSession getSSLSession() {
+ return getValidConnection().getSSLSession();
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder("CPoolProxy{");
+ final ManagedNHttpClientConnection conn = getConnection();
+ if (conn != null) {
+ sb.append(conn);
+ } else {
+ sb.append("detached");
+ }
+ sb.append('}');
+ return sb.toString();
}
}
Modified: httpcomponents/httpasyncclient/branches/4.0.x/httpasyncclient/src/test/java/org/apache/http/impl/nio/conn/TestPoolingHttpClientAsyncConnectionManager.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpasyncclient/branches/4.0.x/httpasyncclient/src/test/java/org/apache/http/impl/nio/conn/TestPoolingHttpClientAsyncConnectionManager.java?rev=1597034&r1=1597033&r2=1597034&view=diff
==============================================================================
--- httpcomponents/httpasyncclient/branches/4.0.x/httpasyncclient/src/test/java/org/apache/http/impl/nio/conn/TestPoolingHttpClientAsyncConnectionManager.java (original)
+++ httpcomponents/httpasyncclient/branches/4.0.x/httpasyncclient/src/test/java/org/apache/http/impl/nio/conn/TestPoolingHttpClientAsyncConnectionManager.java Fri May 23 08:58:53 2014
@@ -26,7 +26,6 @@
*/
package org.apache.http.impl.nio.conn;
-import java.lang.reflect.Proxy;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.Calendar;
@@ -34,8 +33,6 @@ import java.util.concurrent.ExecutionExc
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
-import junit.framework.Assert;
-
import org.apache.commons.logging.Log;
import org.apache.http.HttpHost;
import org.apache.http.concurrent.FutureCallback;
@@ -58,6 +55,7 @@ import org.apache.http.nio.reactor.IOSes
import org.apache.http.nio.reactor.SessionRequest;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
+import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
@@ -146,7 +144,6 @@ public class TestPoolingHttpClientAsyncC
Assert.assertTrue(future.isDone());
final NHttpClientConnection managedConn = future.get();
- Assert.assertTrue(Proxy.isProxyClass(managedConn.getClass()));
Mockito.verify(connCallback).completed(Mockito.<NHttpClientConnection>any());
Mockito.when(conn.isOpen()).thenReturn(Boolean.TRUE);
@@ -182,7 +179,6 @@ public class TestPoolingHttpClientAsyncC
Assert.assertTrue(future.isDone());
final NHttpClientConnection managedConn = future.get();
- Assert.assertTrue(Proxy.isProxyClass(managedConn.getClass()));
Mockito.verify(connCallback).completed(Mockito.<NHttpClientConnection>any());
Mockito.when(conn.isOpen()).thenReturn(Boolean.TRUE);