HTTPCLIENT-953: IllegalStateException thrown by RouteSpecificPool
Contributed by Guillaume <gueugaie at gmail.com> git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@954258 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
5f8e3d49de
commit
0bb63c609a
|
@ -1,6 +1,9 @@
|
|||
Changes since 4.1 ALPHA2
|
||||
-------------------
|
||||
|
||||
* [HTTPCLIENT-953] IllegalStateException thrown by RouteSpecificPool.
|
||||
Contributed by Guillaume <gueugaie at gmail.com>
|
||||
|
||||
* [HTTPCLIENT-952] Trust store parameter is ingored by SSLSocketFactory
|
||||
(affects version 4.1-alpha2 only)
|
||||
Contributed by Oleg Kalnichevski <olegk at apache.org>
|
||||
|
|
|
@ -333,6 +333,9 @@ public class ConnPoolByRoute extends AbstractConnPool {
|
|||
} else if (hasCapacity && !freeConnections.isEmpty()) {
|
||||
|
||||
deleteLeastUsedEntry();
|
||||
// if least used entry's route was the same as rospl,
|
||||
// rospl is now out of date : we preemptively refresh
|
||||
rospl = getRoutePool(route, true);
|
||||
entry = createEntry(rospl, operator);
|
||||
|
||||
} else {
|
||||
|
|
|
@ -198,4 +198,80 @@ public class TestStatefulConnManagement extends ServerTestBase {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRouteSpecificPoolRecylcing() throws Exception {
|
||||
// This tests what happens when a maxed connection pool needs
|
||||
// to kill the last idle connection to a route to build a new
|
||||
// one to the same route.
|
||||
|
||||
int maxConn = 2;
|
||||
|
||||
int port = this.localServer.getServiceAddress().getPort();
|
||||
this.localServer.register("*", new SimpleService());
|
||||
|
||||
// We build a client with 2 max active // connections, and 2 max per route.
|
||||
ThreadSafeClientConnManager connMngr = new ThreadSafeClientConnManager(supportedSchemes);
|
||||
connMngr.setMaxTotalConnections(maxConn);
|
||||
connMngr.setDefaultMaxPerRoute(maxConn);
|
||||
|
||||
DefaultHttpClient client = new DefaultHttpClient(connMngr);
|
||||
|
||||
client.setUserTokenHandler(new UserTokenHandler() {
|
||||
|
||||
public Object getUserToken(final HttpContext context) {
|
||||
return context.getAttribute("user");
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// Bottom of the pool : a *keep alive* connection to Route 1.
|
||||
HttpContext context1 = new BasicHttpContext();
|
||||
context1.setAttribute("user", "stuff");
|
||||
HttpResponse response1 = client.execute(
|
||||
new HttpHost("localhost", port), new HttpGet("/"), context1);
|
||||
HttpEntity entity1 = response1.getEntity();
|
||||
if (entity1 != null) {
|
||||
entity1.consumeContent();
|
||||
}
|
||||
|
||||
// The ConnPoolByRoute now has 1 free connection, out of 2 max
|
||||
// The ConnPoolByRoute has one RouteSpcfcPool, that has one free connection
|
||||
// for [localhost][stuff]
|
||||
|
||||
Thread.sleep(100);
|
||||
|
||||
// Send a very simple HTTP get (it MUST be simple, no auth, no proxy, no 302, no 401, ...)
|
||||
// Send it to another route. Must be a keepalive.
|
||||
HttpContext context2 = new BasicHttpContext();
|
||||
HttpResponse response2 = client.execute(
|
||||
new HttpHost("127.0.0.1", port), new HttpGet("/"), context2);
|
||||
HttpEntity entity2 = response2.getEntity();
|
||||
if (entity2 != null) {
|
||||
entity2.consumeContent();
|
||||
}
|
||||
// ConnPoolByRoute now has 2 free connexions, out of its 2 max.
|
||||
// The [localhost][stuff] RouteSpcfcPool is the same as earlier
|
||||
// And there is a [127.0.0.1][null] pool with 1 free connection
|
||||
|
||||
Thread.sleep(100);
|
||||
|
||||
// This will put the ConnPoolByRoute to the targeted state :
|
||||
// [localhost][stuff] will not get reused because this call is [localhost][null]
|
||||
// So the ConnPoolByRoute will need to kill one connection (it is maxed out globally).
|
||||
// The killed conn is the oldest, which means the first HTTPGet ([localhost][stuff]).
|
||||
// When this happens, the RouteSpecificPool becomes empty.
|
||||
HttpContext context3 = new BasicHttpContext();
|
||||
HttpResponse response3 = client.execute(
|
||||
new HttpHost("localhost", port), new HttpGet("/"), context3);
|
||||
|
||||
// If the ConnPoolByRoute did not behave coherently with the RouteSpecificPool
|
||||
// this may fail. Ex : if the ConnPool discared the route pool because it was empty,
|
||||
// but still used it to build the request3 connection.
|
||||
HttpEntity entity3 = response3.getEntity();
|
||||
if (entity3 != null) {
|
||||
entity3.consumeContent();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue