You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jmeter.apache.org by pm...@apache.org on 2017/02/22 13:08:45 UTC
svn commit: r1784019 - in
/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler: ./
hc/
Author: pmouawad
Date: Wed Feb 22 13:08:45 2017
New Revision: 1784019
URL: http://svn.apache.org/viewvc?rev=1784019&view=rev
Log:
Drop Hack of using hc4 package and import in project the required classes of HC4:
See related https://github.com/apache/httpclient/pull/65
Added:
jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/hc/
jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/hc/HttpConnPool.java (with props)
jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/hc/HttpPoolEntry.java (with props)
jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/hc/JMeterPoolingClientConnectionManager.java (with props)
jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/hc/ManagedClientConnectionImpl.java (with props)
Modified:
jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/MeasuringConnectionManager.java
Modified: jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/MeasuringConnectionManager.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/MeasuringConnectionManager.java?rev=1784019&r1=1784018&r2=1784019&view=diff
==============================================================================
--- jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/MeasuringConnectionManager.java (original)
+++ jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/MeasuringConnectionManager.java Wed Feb 22 13:08:45 2017
@@ -38,10 +38,10 @@ import org.apache.http.conn.DnsResolver;
import org.apache.http.conn.ManagedClientConnection;
import org.apache.http.conn.routing.HttpRoute;
import org.apache.http.conn.scheme.SchemeRegistry;
-import org.apache.http.impl.conn.JMeterPoolingClientConnectionManager;
import org.apache.http.impl.conn.PoolingClientConnectionManager;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HttpContext;
+import org.apache.jmeter.protocol.http.sampler.hc.JMeterPoolingClientConnectionManager;
import org.apache.jmeter.samplers.SampleResult;
/**
Added: jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/hc/HttpConnPool.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/hc/HttpConnPool.java?rev=1784019&view=auto
==============================================================================
--- jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/hc/HttpConnPool.java (added)
+++ jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/hc/HttpConnPool.java Wed Feb 22 13:08:45 2017
@@ -0,0 +1,76 @@
+/*
+ * 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.jmeter.protocol.http.sampler.hc;
+
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.LongAccumulator;
+import java.util.concurrent.atomic.LongAdder;
+
+import org.apache.http.conn.ClientConnectionOperator;
+import org.apache.http.conn.OperatedClientConnection;
+import org.apache.http.conn.routing.HttpRoute;
+import org.apache.http.pool.AbstractConnPool;
+import org.apache.http.pool.ConnFactory;
+import org.slf4j.Logger;
+
+/**
+ * Implementation of AbstractConnPool to allow better connection validity
+ * management.
+ * @since 3.2
+ */
+public class HttpConnPool extends AbstractConnPool<HttpRoute, OperatedClientConnection, HttpPoolEntry> {
+
+ private static final LongAdder COUNTER = new LongAdder();
+
+ private final Logger log;
+ private final long timeToLive;
+ private final TimeUnit tunit;
+
+ public HttpConnPool(final Logger log,
+ final ClientConnectionOperator connOperator,
+ final int defaultMaxPerRoute, final int maxTotal,
+ final long timeToLive, final TimeUnit tunit) {
+ super(new InternalConnFactory(connOperator), defaultMaxPerRoute, maxTotal);
+ this.log = log;
+ this.timeToLive = timeToLive;
+ this.tunit = tunit;
+ }
+
+ @Override
+ protected HttpPoolEntry createEntry(final HttpRoute route, final OperatedClientConnection conn) {
+ final String id = Long.toString(COUNTER.sum());
+ return new HttpPoolEntry(this.log, id, route, conn, this.timeToLive, this.tunit);
+ }
+
+ static class InternalConnFactory implements ConnFactory<HttpRoute, OperatedClientConnection> {
+
+ private final ClientConnectionOperator connOperator;
+
+ InternalConnFactory(final ClientConnectionOperator connOperator) {
+ this.connOperator = connOperator;
+ }
+
+ @Override
+ public OperatedClientConnection create(final HttpRoute route) throws IOException {
+ return connOperator.createConnection();
+ }
+ }
+}
Propchange: jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/hc/HttpConnPool.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/hc/HttpConnPool.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/hc/HttpPoolEntry.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/hc/HttpPoolEntry.java?rev=1784019&view=auto
==============================================================================
--- jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/hc/HttpPoolEntry.java (added)
+++ jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/hc/HttpPoolEntry.java Wed Feb 22 13:08:45 2017
@@ -0,0 +1,87 @@
+/*
+ * 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.jmeter.protocol.http.sampler.hc;
+
+import java.io.IOException;
+import java.util.Date;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.http.conn.OperatedClientConnection;
+import org.apache.http.conn.routing.HttpRoute;
+import org.apache.http.conn.routing.RouteTracker;
+import org.apache.http.pool.PoolEntry;
+import org.slf4j.Logger;
+
+/**
+ * Implementation of {@link PoolEntry}
+ * @since 3.2
+ */
+public class HttpPoolEntry extends PoolEntry<HttpRoute, OperatedClientConnection> {
+
+ private final Logger log;
+ private final RouteTracker tracker;
+
+ public HttpPoolEntry(
+ final Logger log,
+ final String id,
+ final HttpRoute route,
+ final OperatedClientConnection conn,
+ final long timeToLive, final TimeUnit tunit) {
+ super(id, route, conn, timeToLive, tunit);
+ this.log = log;
+ this.tracker = new RouteTracker(route);
+ }
+
+ @Override
+ public boolean isExpired(final long now) {
+ final boolean expired = super.isExpired(now);
+ if (expired && this.log.isDebugEnabled()) {
+ this.log.debug("Connection {} expired at {}", this, new Date(getExpiry()));
+ }
+ return expired;
+ }
+
+ RouteTracker getTracker() {
+ return this.tracker;
+ }
+
+ HttpRoute getPlannedRoute() {
+ return getRoute();
+ }
+
+ HttpRoute getEffectiveRoute() {
+ return this.tracker.toRoute();
+ }
+
+ @Override
+ public boolean isClosed() {
+ final OperatedClientConnection conn = getConnection();
+ return !conn.isOpen();
+ }
+
+ @Override
+ public void close() {
+ final OperatedClientConnection conn = getConnection();
+ try {
+ conn.close();
+ } catch (final IOException ex) {
+ this.log.debug("I/O error closing connection", ex);
+ }
+ }
+}
Propchange: jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/hc/HttpPoolEntry.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/hc/HttpPoolEntry.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/hc/JMeterPoolingClientConnectionManager.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/hc/JMeterPoolingClientConnectionManager.java?rev=1784019&view=auto
==============================================================================
--- jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/hc/JMeterPoolingClientConnectionManager.java (added)
+++ jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/hc/JMeterPoolingClientConnectionManager.java Wed Feb 22 13:08:45 2017
@@ -0,0 +1,364 @@
+/*
+ * 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.jmeter.protocol.http.sampler.hc;
+
+import java.io.IOException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import org.apache.http.conn.ClientConnectionManager;
+import org.apache.http.conn.ClientConnectionOperator;
+import org.apache.http.conn.ClientConnectionRequest;
+import org.apache.http.conn.ConnectionPoolTimeoutException;
+import org.apache.http.conn.DnsResolver;
+import org.apache.http.conn.ManagedClientConnection;
+import org.apache.http.conn.routing.HttpRoute;
+import org.apache.http.conn.scheme.SchemeRegistry;
+import org.apache.http.impl.conn.DefaultClientConnectionOperator;
+import org.apache.http.impl.conn.PoolingClientConnectionManager;
+import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
+import org.apache.http.impl.conn.SchemeRegistryFactory;
+import org.apache.http.impl.conn.SystemDefaultDnsResolver;
+import org.apache.http.pool.ConnPoolControl;
+import org.apache.http.pool.PoolStats;
+import org.apache.http.util.Args;
+import org.apache.http.util.Asserts;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Copy/Paste of {@link PoolingClientConnectionManager} with a slight modification
+ * extracted from {@link PoolingHttpClientConnectionManager} to allow using
+ * better validation mechanism introduced in 4.4
+ * TODO : Remove when full upgrade to new HttpClient 4.5.X API is finished
+ * Internal class, DO NOT USE
+ */
+public class JMeterPoolingClientConnectionManager implements ClientConnectionManager, ConnPoolControl<HttpRoute> {
+
+ private static final int VALIDATE_AFTER_INACTIVITY_DEFAULT = 1700;
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ private final SchemeRegistry schemeRegistry;
+
+ private final HttpConnPool pool;
+
+ private final ClientConnectionOperator operator;
+
+
+ /** the custom-configured DNS lookup mechanism. */
+ private final DnsResolver dnsResolver;
+
+ public JMeterPoolingClientConnectionManager(final SchemeRegistry schreg) {
+ this(schreg, -1, TimeUnit.MILLISECONDS);
+ }
+
+ public JMeterPoolingClientConnectionManager(final SchemeRegistry schreg,final DnsResolver dnsResolver) {
+ this(schreg, -1, TimeUnit.MILLISECONDS,dnsResolver);
+ }
+
+ public JMeterPoolingClientConnectionManager() {
+ this(SchemeRegistryFactory.createDefault());
+ }
+
+ public JMeterPoolingClientConnectionManager(
+ final SchemeRegistry schemeRegistry,
+ final long timeToLive, final TimeUnit tunit) {
+ this(schemeRegistry, timeToLive, tunit, new SystemDefaultDnsResolver());
+ }
+
+ public JMeterPoolingClientConnectionManager(
+ final SchemeRegistry schemeRegistry,
+ final long timeToLive, final TimeUnit tunit,
+ final DnsResolver dnsResolver) {
+ this(schemeRegistry, timeToLive, tunit, dnsResolver, VALIDATE_AFTER_INACTIVITY_DEFAULT);
+ }
+
+ public JMeterPoolingClientConnectionManager(final SchemeRegistry schemeRegistry,
+ final long timeToLive, final TimeUnit tunit,
+ final DnsResolver dnsResolver,
+ int validateAfterInactivity) {
+ super();
+ Args.notNull(schemeRegistry, "Scheme registry");
+ Args.notNull(dnsResolver, "DNS resolver");
+ this.schemeRegistry = schemeRegistry;
+ this.dnsResolver = dnsResolver;
+ this.operator = createConnectionOperator(schemeRegistry);
+ this.pool = new HttpConnPool(this.log, this.operator, 2, 20, timeToLive, tunit) {
+ /**
+ * @see org.apache.http.pool.AbstractConnPool#validate(org.apache.http.pool.PoolEntry)
+ */
+ @Override
+ protected boolean validate(HttpPoolEntry entry) {
+ return !entry.getConnection().isStale();
+ }
+
+ };
+ pool.setValidateAfterInactivity(validateAfterInactivity);
+ }
+
+ /**
+ * @see #setValidateAfterInactivity(int)
+ *
+ * @since 4.5.2
+ */
+ public int getValidateAfterInactivity() {
+ return pool.getValidateAfterInactivity();
+ }
+
+ /**
+ * Defines period of inactivity in milliseconds after which persistent connections must
+ * be re-validated prior to being {@link #leaseConnection(java.util.concurrent.Future,
+ * long, java.util.concurrent.TimeUnit) leased} to the consumer. Non-positive value passed
+ * to this method disables connection validation. This check helps detect connections
+ * that have become stale (half-closed) while kept inactive in the pool.
+ *
+ * @see #leaseConnection(java.util.concurrent.Future, long, java.util.concurrent.TimeUnit)
+ *
+ * @since 4.5.2
+ */
+ public void setValidateAfterInactivity(final int ms) {
+ pool.setValidateAfterInactivity(ms);
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ shutdown();
+ } finally {
+ super.finalize();
+ }
+ }
+
+ /**
+ * Hook for creating the connection operator.
+ * It is called by the constructor.
+ * Derived classes can override this method to change the
+ * instantiation of the operator.
+ * The default implementation here instantiates
+ * {@link DefaultClientConnectionOperator DefaultClientConnectionOperator}.
+ *
+ * @param schreg the scheme registry.
+ *
+ * @return the connection operator to use
+ */
+ protected ClientConnectionOperator createConnectionOperator(final SchemeRegistry schreg) {
+ return new DefaultClientConnectionOperator(schreg, this.dnsResolver);
+ }
+ @Override
+ public SchemeRegistry getSchemeRegistry() {
+ return this.schemeRegistry;
+ }
+
+ private String format(final HttpRoute route, final Object state) {
+ final StringBuilder buf = new StringBuilder();
+ buf.append("[route: ").append(route).append("]");
+ if (state != null) {
+ buf.append("[state: ").append(state).append("]");
+ }
+ return buf.toString();
+ }
+
+ private String formatStats(final HttpRoute route) {
+ final StringBuilder buf = new StringBuilder();
+ final PoolStats totals = this.pool.getTotalStats();
+ final PoolStats stats = this.pool.getStats(route);
+ buf.append("[total kept alive: ").append(totals.getAvailable()).append("; ");
+ buf.append("route allocated: ").append(stats.getLeased() + stats.getAvailable());
+ buf.append(" of ").append(stats.getMax()).append("; ");
+ buf.append("total allocated: ").append(totals.getLeased() + totals.getAvailable());
+ buf.append(" of ").append(totals.getMax()).append("]");
+ return buf.toString();
+ }
+
+ private String format(final HttpPoolEntry entry) {
+ final StringBuilder buf = new StringBuilder();
+ buf.append("[id: ").append(entry.getId()).append("]");
+ buf.append("[route: ").append(entry.getRoute()).append("]");
+ final Object state = entry.getState();
+ if (state != null) {
+ buf.append("[state: ").append(state).append("]");
+ }
+ return buf.toString();
+ }
+
+ @Override
+ public ClientConnectionRequest requestConnection(
+ final HttpRoute route,
+ final Object state) {
+ Args.notNull(route, "HTTP route");
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Connection request: "+format(route, state)
+ +", stats:"+formatStats(route)+", pool:"+ pool);
+ }
+ final Future<HttpPoolEntry> future = this.pool.lease(route, state);
+
+ return new ClientConnectionRequest() {
+ @Override
+ public void abortRequest() {
+ future.cancel(true);
+ }
+ @Override
+ public ManagedClientConnection getConnection(
+ final long timeout,
+ final TimeUnit tunit) throws InterruptedException, ConnectionPoolTimeoutException {
+ return leaseConnection(future, timeout, tunit);
+ }
+
+ };
+
+ }
+
+ ManagedClientConnection leaseConnection(
+ final Future<HttpPoolEntry> future,
+ final long timeout,
+ final TimeUnit tunit) throws InterruptedException, ConnectionPoolTimeoutException {
+ final HttpPoolEntry entry;
+ try {
+ entry = future.get(timeout, tunit);
+ if (entry == null || future.isCancelled()) {
+ throw new InterruptedException();
+ }
+ Asserts.check(entry.getConnection() != null, "Pool entry with no connection");
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Connection leased: " + format(entry) + formatStats(entry.getRoute()));
+ }
+ return new ManagedClientConnectionImpl(this, this.operator, entry);
+ } catch (final ExecutionException ex) {
+ Throwable cause = ex.getCause();
+ if (cause == null) {
+ cause = ex;
+ }
+ this.log.error("Unexpected exception leasing connection from pool", cause);
+ // Should never happen
+ throw new InterruptedException();
+ } catch (final TimeoutException ex) {
+ throw new ConnectionPoolTimeoutException("Timeout waiting for connection from pool");
+ }
+ }
+ @Override
+ public void releaseConnection(
+ final ManagedClientConnection conn, final long keepalive, final TimeUnit tunit) {
+
+ Args.check(conn instanceof ManagedClientConnectionImpl, "Connection class mismatch, " +
+ "connection not obtained from this manager");
+ final ManagedClientConnectionImpl managedConn = (ManagedClientConnectionImpl) conn;
+ Asserts.check(managedConn.getManager() == this, "Connection not obtained from this manager");
+ synchronized (managedConn) {
+ final HttpPoolEntry entry = managedConn.detach();
+ if (entry == null) {
+ return;
+ }
+ try {
+ if (managedConn.isOpen() && !managedConn.isMarkedReusable()) {
+ try {
+ managedConn.shutdown();
+ } catch (final IOException iox) {
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("I/O exception shutting down released connection", iox);
+ }
+ }
+ }
+ // Only reusable connections can be kept alive
+ if (managedConn.isMarkedReusable()) {
+ entry.updateExpiry(keepalive, tunit != null ? tunit : TimeUnit.MILLISECONDS);
+ if (this.log.isDebugEnabled()) {
+ final String s;
+ if (keepalive > 0) {
+ s = "for " + keepalive + " " + tunit;
+ } else {
+ s = "indefinitely";
+ }
+ this.log.debug("Connection " + format(entry) + " can be kept alive " + s);
+ }
+ }
+ } finally {
+ this.pool.release(entry, managedConn.isMarkedReusable());
+ }
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Connection released: " + format(entry) + formatStats(entry.getRoute()));
+ }
+ }
+ }
+ @Override
+ public void shutdown() {
+ this.log.debug("Connection manager is shutting down");
+ try {
+ this.pool.shutdown();
+ } catch (final IOException ex) {
+ this.log.debug("I/O exception shutting down connection manager", ex);
+ }
+ this.log.debug("Connection manager shut down");
+ }
+ @Override
+ public void closeIdleConnections(final long idleTimeout, final TimeUnit tunit) {
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Closing connections idle longer than " + idleTimeout + " " + tunit);
+ }
+ this.pool.closeIdle(idleTimeout, tunit);
+ }
+ @Override
+ public void closeExpiredConnections() {
+ this.log.debug("Closing expired connections");
+ this.pool.closeExpired();
+ }
+ @Override
+ public int getMaxTotal() {
+ return this.pool.getMaxTotal();
+ }
+ @Override
+ public void setMaxTotal(final int max) {
+ this.pool.setMaxTotal(max);
+ }
+ @Override
+ public int getDefaultMaxPerRoute() {
+ return this.pool.getDefaultMaxPerRoute();
+ }
+ @Override
+ public void setDefaultMaxPerRoute(final int max) {
+ this.pool.setDefaultMaxPerRoute(max);
+ }
+ @Override
+ public int getMaxPerRoute(final HttpRoute route) {
+ return this.pool.getMaxPerRoute(route);
+ }
+ @Override
+ public void setMaxPerRoute(final HttpRoute route, final int max) {
+ this.pool.setMaxPerRoute(route, max);
+ }
+ @Override
+ public PoolStats getTotalStats() {
+ return this.pool.getTotalStats();
+ }
+ @Override
+ public PoolStats getStats(final HttpRoute route) {
+ return this.pool.getStats(route);
+ }
+
+ /**
+ * @return the dnsResolver
+ */
+ protected DnsResolver getDnsResolver() {
+ return dnsResolver;
+ }
+
+}
+
Propchange: jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/hc/JMeterPoolingClientConnectionManager.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/hc/JMeterPoolingClientConnectionManager.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/hc/ManagedClientConnectionImpl.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/hc/ManagedClientConnectionImpl.java?rev=1784019&view=auto
==============================================================================
--- jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/hc/ManagedClientConnectionImpl.java (added)
+++ jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/hc/ManagedClientConnectionImpl.java Wed Feb 22 13:08:45 2017
@@ -0,0 +1,486 @@
+/*
+ * 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.jmeter.protocol.http.sampler.hc;
+
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.util.concurrent.TimeUnit;
+
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocket;
+
+import org.apache.http.HttpConnectionMetrics;
+import org.apache.http.HttpEntityEnclosingRequest;
+import org.apache.http.HttpException;
+import org.apache.http.HttpHost;
+import org.apache.http.HttpRequest;
+import org.apache.http.HttpResponse;
+import org.apache.http.conn.ClientConnectionManager;
+import org.apache.http.conn.ClientConnectionOperator;
+import org.apache.http.conn.ManagedClientConnection;
+import org.apache.http.conn.OperatedClientConnection;
+import org.apache.http.conn.routing.HttpRoute;
+import org.apache.http.conn.routing.RouteTracker;
+import org.apache.http.impl.conn.ConnectionShutdownException;
+import org.apache.http.params.HttpParams;
+import org.apache.http.protocol.HttpContext;
+import org.apache.http.util.Args;
+import org.apache.http.util.Asserts;
+
+/**
+ * Implementation of {@link ManagedClientConnection}
+ * @since 3.2
+ *
+ */
+public class ManagedClientConnectionImpl implements ManagedClientConnection {
+
+ private final ClientConnectionManager manager;
+ private final ClientConnectionOperator operator;
+ private volatile HttpPoolEntry poolEntry;
+ private volatile boolean reusable;
+ private volatile long duration;
+
+ public ManagedClientConnectionImpl(
+ final ClientConnectionManager manager,
+ final ClientConnectionOperator operator,
+ final HttpPoolEntry entry) {
+ super();
+ Args.notNull(manager, "Connection manager");
+ Args.notNull(operator, "Connection operator");
+ Args.notNull(entry, "HTTP pool entry");
+ this.manager = manager;
+ this.operator = operator;
+ this.poolEntry = entry;
+ this.reusable = false;
+ this.duration = Long.MAX_VALUE;
+ }
+
+ @Override
+ public String getId() {
+ return null;
+ }
+
+ HttpPoolEntry getPoolEntry() {
+ return this.poolEntry;
+ }
+
+ public HttpPoolEntry detach() {
+ final HttpPoolEntry local = this.poolEntry;
+ this.poolEntry = null;
+ return local;
+ }
+
+ public ClientConnectionManager getManager() {
+ return this.manager;
+ }
+
+ private OperatedClientConnection getConnection() {
+ final HttpPoolEntry local = this.poolEntry;
+ if (local == null) {
+ return null;
+ }
+ return local.getConnection();
+ }
+
+ private OperatedClientConnection ensureConnection() {
+ final HttpPoolEntry local = this.poolEntry;
+ if (local == null) {
+ throw new ConnectionShutdownException();
+ }
+ return local.getConnection();
+ }
+
+ private HttpPoolEntry ensurePoolEntry() {
+ final HttpPoolEntry local = this.poolEntry;
+ if (local == null) {
+ throw new ConnectionShutdownException();
+ }
+ return local;
+ }
+
+ @Override
+ public void close() throws IOException {
+ final HttpPoolEntry local = this.poolEntry;
+ if (local != null) {
+ final OperatedClientConnection conn = local.getConnection();
+ local.getTracker().reset();
+ conn.close();
+ }
+ }
+
+ @Override
+ public void shutdown() throws IOException {
+ final HttpPoolEntry local = this.poolEntry;
+ if (local != null) {
+ final OperatedClientConnection conn = local.getConnection();
+ local.getTracker().reset();
+ conn.shutdown();
+ }
+ }
+
+ @Override
+ public boolean isOpen() {
+ final OperatedClientConnection conn = getConnection();
+ if (conn != null) {
+ return conn.isOpen();
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public boolean isStale() {
+ final OperatedClientConnection conn = getConnection();
+ if (conn != null) {
+ return conn.isStale();
+ } else {
+ return true;
+ }
+ }
+
+ @Override
+ public void setSocketTimeout(final int timeout) {
+ final OperatedClientConnection conn = ensureConnection();
+ conn.setSocketTimeout(timeout);
+ }
+
+ @Override
+ public int getSocketTimeout() {
+ final OperatedClientConnection conn = ensureConnection();
+ return conn.getSocketTimeout();
+ }
+
+ @Override
+ public HttpConnectionMetrics getMetrics() {
+ final OperatedClientConnection conn = ensureConnection();
+ return conn.getMetrics();
+ }
+
+ @Override
+ public void flush() throws IOException {
+ final OperatedClientConnection conn = ensureConnection();
+ conn.flush();
+ }
+
+ @Override
+ public boolean isResponseAvailable(final int timeout) throws IOException {
+ final OperatedClientConnection conn = ensureConnection();
+ return conn.isResponseAvailable(timeout);
+ }
+
+ @Override
+ public void receiveResponseEntity(
+ final HttpResponse response) throws HttpException, IOException {
+ final OperatedClientConnection conn = ensureConnection();
+ conn.receiveResponseEntity(response);
+ }
+
+ @Override
+ public HttpResponse receiveResponseHeader() throws HttpException, IOException {
+ final OperatedClientConnection conn = ensureConnection();
+ return conn.receiveResponseHeader();
+ }
+
+ @Override
+ public void sendRequestEntity(
+ final HttpEntityEnclosingRequest request) throws HttpException, IOException {
+ final OperatedClientConnection conn = ensureConnection();
+ conn.sendRequestEntity(request);
+ }
+
+ @Override
+ public void sendRequestHeader(
+ final HttpRequest request) throws HttpException, IOException {
+ final OperatedClientConnection conn = ensureConnection();
+ conn.sendRequestHeader(request);
+ }
+
+ @Override
+ public InetAddress getLocalAddress() {
+ final OperatedClientConnection conn = ensureConnection();
+ return conn.getLocalAddress();
+ }
+
+ @Override
+ public int getLocalPort() {
+ final OperatedClientConnection conn = ensureConnection();
+ return conn.getLocalPort();
+ }
+
+ @Override
+ public InetAddress getRemoteAddress() {
+ final OperatedClientConnection conn = ensureConnection();
+ return conn.getRemoteAddress();
+ }
+
+ @Override
+ public int getRemotePort() {
+ final OperatedClientConnection conn = ensureConnection();
+ return conn.getRemotePort();
+ }
+
+ @Override
+ public boolean isSecure() {
+ final OperatedClientConnection conn = ensureConnection();
+ return conn.isSecure();
+ }
+
+ @Override
+ public void bind(final Socket socket) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Socket getSocket() {
+ final OperatedClientConnection conn = ensureConnection();
+ return conn.getSocket();
+ }
+
+ @Override
+ public SSLSession getSSLSession() {
+ final OperatedClientConnection conn = ensureConnection();
+ SSLSession result = null;
+ final Socket sock = conn.getSocket();
+ if (sock instanceof SSLSocket) {
+ result = ((SSLSocket)sock).getSession();
+ }
+ return result;
+ }
+
+ public Object getAttribute(final String id) {
+ final OperatedClientConnection conn = ensureConnection();
+ if (conn instanceof HttpContext) {
+ return ((HttpContext) conn).getAttribute(id);
+ } else {
+ return null;
+ }
+ }
+
+ public Object removeAttribute(final String id) {
+ final OperatedClientConnection conn = ensureConnection();
+ if (conn instanceof HttpContext) {
+ return ((HttpContext) conn).removeAttribute(id);
+ } else {
+ return null;
+ }
+ }
+
+ public void setAttribute(final String id, final Object obj) {
+ final OperatedClientConnection conn = ensureConnection();
+ if (conn instanceof HttpContext) {
+ ((HttpContext) conn).setAttribute(id, obj);
+ }
+ }
+
+ @Override
+ public HttpRoute getRoute() {
+ final HttpPoolEntry local = ensurePoolEntry();
+ return local.getEffectiveRoute();
+ }
+
+ @Override
+ public void open(
+ final HttpRoute route,
+ final HttpContext context,
+ final HttpParams params) throws IOException {
+ Args.notNull(route, "Route");
+ Args.notNull(params, "HTTP parameters");
+ final OperatedClientConnection conn;
+ synchronized (this) {
+ if (this.poolEntry == null) {
+ throw new ConnectionShutdownException();
+ }
+ final RouteTracker tracker = this.poolEntry.getTracker();
+ Asserts.notNull(tracker, "Route tracker");
+ Asserts.check(!tracker.isConnected(), "Connection already open");
+ conn = this.poolEntry.getConnection();
+ }
+
+ final HttpHost proxy = route.getProxyHost();
+ this.operator.openConnection(
+ conn,
+ (proxy != null) ? proxy : route.getTargetHost(),
+ route.getLocalAddress(),
+ context, params);
+
+ synchronized (this) {
+ if (this.poolEntry == null) {
+ throw new InterruptedIOException();
+ }
+ final RouteTracker tracker = this.poolEntry.getTracker();
+ if (proxy == null) {
+ tracker.connectTarget(conn.isSecure());
+ } else {
+ tracker.connectProxy(proxy, conn.isSecure());
+ }
+ }
+ }
+
+ @Override
+ public void tunnelTarget(
+ final boolean secure, final HttpParams params) throws IOException {
+ Args.notNull(params, "HTTP parameters");
+ final HttpHost target;
+ final OperatedClientConnection conn;
+ synchronized (this) {
+ if (this.poolEntry == null) {
+ throw new ConnectionShutdownException();
+ }
+ final RouteTracker tracker = this.poolEntry.getTracker();
+ Asserts.notNull(tracker, "Route tracker");
+ Asserts.check(tracker.isConnected(), "Connection not open");
+ Asserts.check(!tracker.isTunnelled(), "Connection is already tunnelled");
+ target = tracker.getTargetHost();
+ conn = this.poolEntry.getConnection();
+ }
+
+ conn.update(null, target, secure, params);
+
+ synchronized (this) {
+ if (this.poolEntry == null) {
+ throw new InterruptedIOException();
+ }
+ final RouteTracker tracker = this.poolEntry.getTracker();
+ tracker.tunnelTarget(secure);
+ }
+ }
+
+ @Override
+ public void tunnelProxy(
+ final HttpHost next, final boolean secure, final HttpParams params) throws IOException {
+ Args.notNull(next, "Next proxy");
+ Args.notNull(params, "HTTP parameters");
+ final OperatedClientConnection conn;
+ synchronized (this) {
+ if (this.poolEntry == null) {
+ throw new ConnectionShutdownException();
+ }
+ final RouteTracker tracker = this.poolEntry.getTracker();
+ Asserts.notNull(tracker, "Route tracker");
+ Asserts.check(tracker.isConnected(), "Connection not open");
+ conn = this.poolEntry.getConnection();
+ }
+
+ conn.update(null, next, secure, params);
+
+ synchronized (this) {
+ if (this.poolEntry == null) {
+ throw new InterruptedIOException();
+ }
+ final RouteTracker tracker = this.poolEntry.getTracker();
+ tracker.tunnelProxy(next, secure);
+ }
+ }
+
+ @Override
+ public void layerProtocol(
+ final HttpContext context, final HttpParams params) throws IOException {
+ Args.notNull(params, "HTTP parameters");
+ final HttpHost target;
+ final OperatedClientConnection conn;
+ synchronized (this) {
+ if (this.poolEntry == null) {
+ throw new ConnectionShutdownException();
+ }
+ final RouteTracker tracker = this.poolEntry.getTracker();
+ Asserts.notNull(tracker, "Route tracker");
+ Asserts.check(tracker.isConnected(), "Connection not open");
+ Asserts.check(tracker.isTunnelled(), "Protocol layering without a tunnel not supported");
+ Asserts.check(!tracker.isLayered(), "Multiple protocol layering not supported");
+ target = tracker.getTargetHost();
+ conn = this.poolEntry.getConnection();
+ }
+ this.operator.updateSecureConnection(conn, target, context, params);
+
+ synchronized (this) {
+ if (this.poolEntry == null) {
+ throw new InterruptedIOException();
+ }
+ final RouteTracker tracker = this.poolEntry.getTracker();
+ tracker.layerProtocol(conn.isSecure());
+ }
+ }
+
+ @Override
+ public Object getState() {
+ final HttpPoolEntry local = ensurePoolEntry();
+ return local.getState();
+ }
+
+ @Override
+ public void setState(final Object state) {
+ final HttpPoolEntry local = ensurePoolEntry();
+ local.setState(state);
+ }
+
+ @Override
+ public void markReusable() {
+ this.reusable = true;
+ }
+
+ @Override
+ public void unmarkReusable() {
+ this.reusable = false;
+ }
+
+ @Override
+ public boolean isMarkedReusable() {
+ return this.reusable;
+ }
+
+ @Override
+ public void setIdleDuration(final long duration, final TimeUnit unit) {
+ if(duration > 0) {
+ this.duration = unit.toMillis(duration);
+ } else {
+ this.duration = -1;
+ }
+ }
+
+ @Override
+ public void releaseConnection() {
+ synchronized (this) {
+ if (this.poolEntry == null) {
+ return;
+ }
+ this.manager.releaseConnection(this, this.duration, TimeUnit.MILLISECONDS);
+ this.poolEntry = null;
+ }
+ }
+
+ @Override
+ public void abortConnection() {
+ synchronized (this) {
+ if (this.poolEntry == null) {
+ return;
+ }
+ this.reusable = false;
+ final OperatedClientConnection conn = this.poolEntry.getConnection();
+ try {
+ conn.shutdown();
+ } catch (final IOException ignore) {
+ }
+ this.manager.releaseConnection(this, this.duration, TimeUnit.MILLISECONDS);
+ this.poolEntry = null;
+ }
+ }
+
+}
Propchange: jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/hc/ManagedClientConnectionImpl.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/hc/ManagedClientConnectionImpl.java
------------------------------------------------------------------------------
svn:mime-type = text/plain