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 2019/09/07 11:08:31 UTC

[httpcomponents-core] branch HTTPCORE-596 created (now c9cf7c6)

This is an automated email from the ASF dual-hosted git repository.

olegk pushed a change to branch HTTPCORE-596
in repository https://gitbox.apache.org/repos/asf/httpcomponents-core.git.


      at c9cf7c6  HTTPCORE-596: connection pools to use an optional callback to close out disposed connections

This branch includes the following new commits:

     new f5bb9a7  Connection pools to close connections gracefully in case of an ordinary connection disposal
     new c9cf7c6  HTTPCORE-596: connection pools to use an optional callback to close out disposed connections

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[httpcomponents-core] 02/02: HTTPCORE-596: connection pools to use an optional callback to close out disposed connections

Posted by ol...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

olegk pushed a commit to branch HTTPCORE-596
in repository https://gitbox.apache.org/repos/asf/httpcomponents-core.git

commit c9cf7c6863197e20bbea7fbff45cecbf88e29492
Author: Oleg Kalnichevski <ol...@apache.org>
AuthorDate: Sat Sep 7 13:01:45 2019 +0200

    HTTPCORE-596: connection pools to use an optional callback to close out disposed connections
---
 .../impl/nio/bootstrap/H2RequesterBootstrap.java   |  3 ++
 .../org/apache/hc/core5/http/HttpConnection.java   | 28 ++---------
 .../apache/hc/core5/http/SocketModalCloseable.java | 54 ++++++++++++++++++++++
 .../impl/bootstrap/AsyncRequesterBootstrap.java    |  3 ++
 .../http/impl/bootstrap/RequesterBootstrap.java    |  3 ++
 .../hc/core5/pool/ConnectionDisposalCallback.java  | 47 +++++++++++++++++++
 .../java/org/apache/hc/core5/pool/LaxConnPool.java | 30 +++++++++---
 .../java/org/apache/hc/core5/pool/PoolEntry.java   | 34 ++++++++++++--
 .../org/apache/hc/core5/pool/StrictConnPool.java   | 27 +++++++++--
 .../org/apache/hc/core5/reactor/IOSession.java     |  4 +-
 10 files changed, 192 insertions(+), 41 deletions(-)

diff --git a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/H2RequesterBootstrap.java b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/H2RequesterBootstrap.java
index ceb8c15..68fc5d4 100644
--- a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/H2RequesterBootstrap.java
+++ b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/H2RequesterBootstrap.java
@@ -53,6 +53,7 @@ import org.apache.hc.core5.http2.impl.nio.H2StreamListener;
 import org.apache.hc.core5.http2.nio.support.DefaultAsyncPushConsumerFactory;
 import org.apache.hc.core5.http2.ssl.H2ClientTlsStrategy;
 import org.apache.hc.core5.pool.ConnPoolListener;
+import org.apache.hc.core5.pool.ConnectionDisposalCallback;
 import org.apache.hc.core5.pool.LaxConnPool;
 import org.apache.hc.core5.pool.ManagedConnPool;
 import org.apache.hc.core5.pool.PoolConcurrencyPolicy;
@@ -291,6 +292,7 @@ public class H2RequesterBootstrap {
                         defaultMaxPerRoute > 0 ? defaultMaxPerRoute : 20,
                         timeToLive,
                         poolReusePolicy,
+                        new ConnectionDisposalCallback<IOSession>(),
                         connPoolListener);
                 break;
             case STRICT:
@@ -300,6 +302,7 @@ public class H2RequesterBootstrap {
                         maxTotal > 0 ? maxTotal : 50,
                         timeToLive,
                         poolReusePolicy,
+                        new ConnectionDisposalCallback<IOSession>(),
                         connPoolListener);
                 break;
         }
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/HttpConnection.java b/httpcore5/src/main/java/org/apache/hc/core5/http/HttpConnection.java
index 8c3eaf1..5b0e330 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/http/HttpConnection.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/HttpConnection.java
@@ -32,15 +32,12 @@ import java.net.SocketAddress;
 
 import javax.net.ssl.SSLSession;
 
-import org.apache.hc.core5.io.ModalCloseable;
-import org.apache.hc.core5.util.Timeout;
-
 /**
  * A generic HTTP connection, useful on client and server side.
  *
  * @since 4.0
  */
-public interface HttpConnection extends ModalCloseable {
+public interface HttpConnection extends SocketModalCloseable {
 
     /**
      * Closes this connection gracefully. This method will attempt to flush the internal output
@@ -66,14 +63,6 @@ public interface HttpConnection extends ModalCloseable {
     SocketAddress getLocalAddress();
 
     /**
-     * Returns this connection's protocol version or {@code null} if unknown.
-     *
-     * @return this connection's protocol version or {@code null} if unknown.
-     * @since 5.0
-     */
-    ProtocolVersion getProtocolVersion();
-
-    /**
      * Returns this connection's remote address or {@code null} if it is not connected yet or
      * unconnected.
      *
@@ -84,19 +73,12 @@ public interface HttpConnection extends ModalCloseable {
     SocketAddress getRemoteAddress();
 
     /**
-     * Returns the socket timeout value.
-     *
-     * @return timeout value.
-     */
-    Timeout getSocketTimeout();
-
-    /**
-     * Sets the socket timeout value.
+     * Returns this connection's protocol version or {@code null} if unknown.
      *
-     * @param timeout
-     *            timeout value
+     * @return this connection's protocol version or {@code null} if unknown.
+     * @since 5.0
      */
-    void setSocketTimeout(Timeout timeout);
+    ProtocolVersion getProtocolVersion();
 
     /**
      * Returns this connection's SSL session or {@code null} if TLS has not been activated.
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/SocketModalCloseable.java b/httpcore5/src/main/java/org/apache/hc/core5/http/SocketModalCloseable.java
new file mode 100644
index 0000000..2597ecc
--- /dev/null
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/SocketModalCloseable.java
@@ -0,0 +1,54 @@
+/*
+ * ====================================================================
+ * 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.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.hc.core5.http;
+
+import org.apache.hc.core5.io.ModalCloseable;
+import org.apache.hc.core5.util.Timeout;
+
+/**
+ * A generic {@link ModalCloseable} backed by a network socket.
+ *
+ * @since 5.0
+ */
+public interface SocketModalCloseable extends ModalCloseable {
+
+    /**
+     * Returns the socket timeout value.
+     *
+     * @return timeout value.
+     */
+    Timeout getSocketTimeout();
+
+    /**
+     * Sets the socket timeout value.
+     *
+     * @param timeout timeout value
+     */
+    void setSocketTimeout(Timeout timeout);
+
+}
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/AsyncRequesterBootstrap.java b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/AsyncRequesterBootstrap.java
index fa910f9..5add2ff 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/AsyncRequesterBootstrap.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/AsyncRequesterBootstrap.java
@@ -41,6 +41,7 @@ import org.apache.hc.core5.http.nio.ssl.BasicClientTlsStrategy;
 import org.apache.hc.core5.http.nio.ssl.TlsStrategy;
 import org.apache.hc.core5.http.protocol.HttpProcessor;
 import org.apache.hc.core5.pool.ConnPoolListener;
+import org.apache.hc.core5.pool.ConnectionDisposalCallback;
 import org.apache.hc.core5.pool.LaxConnPool;
 import org.apache.hc.core5.pool.ManagedConnPool;
 import org.apache.hc.core5.pool.PoolConcurrencyPolicy;
@@ -218,6 +219,7 @@ public class AsyncRequesterBootstrap {
                         defaultMaxPerRoute > 0 ? defaultMaxPerRoute : 20,
                         timeToLive,
                         poolReusePolicy,
+                        new ConnectionDisposalCallback<IOSession>(),
                         connPoolListener);
                 break;
             case STRICT:
@@ -227,6 +229,7 @@ public class AsyncRequesterBootstrap {
                         maxTotal > 0 ? maxTotal : 50,
                         timeToLive,
                         poolReusePolicy,
+                        new ConnectionDisposalCallback<IOSession>(),
                         connPoolListener);
                 break;
         }
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/RequesterBootstrap.java b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/RequesterBootstrap.java
index 929bfdc..0f11f0b 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/RequesterBootstrap.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/RequesterBootstrap.java
@@ -49,6 +49,7 @@ import org.apache.hc.core5.http.io.ssl.DefaultTlsSetupHandler;
 import org.apache.hc.core5.http.io.ssl.SSLSessionVerifier;
 import org.apache.hc.core5.http.protocol.HttpProcessor;
 import org.apache.hc.core5.pool.ConnPoolListener;
+import org.apache.hc.core5.pool.ConnectionDisposalCallback;
 import org.apache.hc.core5.pool.LaxConnPool;
 import org.apache.hc.core5.pool.ManagedConnPool;
 import org.apache.hc.core5.pool.PoolConcurrencyPolicy;
@@ -188,6 +189,7 @@ public class RequesterBootstrap {
                         defaultMaxPerRoute > 0 ? defaultMaxPerRoute : 20,
                         timeToLive,
                         poolReusePolicy,
+                        new ConnectionDisposalCallback<HttpClientConnection>(),
                         connPoolListener);
                 break;
             case STRICT:
@@ -197,6 +199,7 @@ public class RequesterBootstrap {
                         maxTotal > 0 ? maxTotal : 50,
                         timeToLive,
                         poolReusePolicy,
+                        new ConnectionDisposalCallback<HttpClientConnection>(),
                         connPoolListener);
                 break;
         }
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/pool/ConnectionDisposalCallback.java b/httpcore5/src/main/java/org/apache/hc/core5/pool/ConnectionDisposalCallback.java
new file mode 100644
index 0000000..42a4d40
--- /dev/null
+++ b/httpcore5/src/main/java/org/apache/hc/core5/pool/ConnectionDisposalCallback.java
@@ -0,0 +1,47 @@
+/*
+ * ====================================================================
+ * 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.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package org.apache.hc.core5.pool;
+
+import org.apache.hc.core5.function.Callback;
+import org.apache.hc.core5.http.SocketModalCloseable;
+import org.apache.hc.core5.io.CloseMode;
+import org.apache.hc.core5.util.Timeout;
+
+public final class ConnectionDisposalCallback<C extends SocketModalCloseable> implements Callback<C> {
+
+    private final static Timeout DEFAULT_CLOSE_TIMEOUT = Timeout.ofSeconds(1L);
+
+    @Override
+    public void execute(final C closeable) {
+        final Timeout socketTimeout = closeable.getSocketTimeout();
+        if (socketTimeout == null || socketTimeout.toMillis() <= 0 || socketTimeout.toMillis() > 1000) {
+            closeable.setSocketTimeout(DEFAULT_CLOSE_TIMEOUT);
+        }
+        closeable.close(CloseMode.GRACEFUL);
+    }
+
+}
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/pool/LaxConnPool.java b/httpcore5/src/main/java/org/apache/hc/core5/pool/LaxConnPool.java
index bab4ce4..34fac16 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/pool/LaxConnPool.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/pool/LaxConnPool.java
@@ -35,9 +35,9 @@ import java.util.concurrent.ConcurrentLinkedDeque;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.Future;
 import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicMarkableReference;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.AtomicMarkableReference;
 
 import org.apache.hc.core5.annotation.Contract;
 import org.apache.hc.core5.annotation.Experimental;
@@ -69,8 +69,9 @@ import org.apache.hc.core5.util.Timeout;
 public class LaxConnPool<T, C extends ModalCloseable> implements ManagedConnPool<T, C> {
 
     private final TimeValue timeToLive;
-    private final ConnPoolListener<T> connPoolListener;
     private final PoolReusePolicy policy;
+    private final Callback<C> disposalCallback;
+    private final ConnPoolListener<T> connPoolListener;
     private final ConcurrentMap<T, PerRoutePool<T, C>> routeToPool;
     private final AtomicBoolean isShutDown;
 
@@ -83,19 +84,32 @@ public class LaxConnPool<T, C extends ModalCloseable> implements ManagedConnPool
             final int defaultMaxPerRoute,
             final TimeValue timeToLive,
             final PoolReusePolicy policy,
+            final Callback<C> disposalCallback,
             final ConnPoolListener<T> connPoolListener) {
         super();
         Args.positive(defaultMaxPerRoute, "Max per route value");
         this.timeToLive = TimeValue.defaultsToNegativeOneMillisecond(timeToLive);
-        this.connPoolListener = connPoolListener;
         this.policy = policy != null ? policy : PoolReusePolicy.LIFO;
+        this.disposalCallback = disposalCallback;
+        this.connPoolListener = connPoolListener;
         this.routeToPool = new ConcurrentHashMap<>();
         this.isShutDown = new AtomicBoolean(false);
         this.defaultMaxPerRoute = defaultMaxPerRoute;
     }
 
+    /**
+     * @since 5.0
+     */
+    public LaxConnPool(
+            final int defaultMaxPerRoute,
+            final TimeValue timeToLive,
+            final PoolReusePolicy policy,
+            final ConnPoolListener<T> connPoolListener) {
+        this(defaultMaxPerRoute, timeToLive, policy, null, connPoolListener);
+    }
+
     public LaxConnPool(final int defaultMaxPerRoute) {
-        this(defaultMaxPerRoute, TimeValue.NEG_ONE_MILLISECONDS, PoolReusePolicy.LIFO, null);
+        this(defaultMaxPerRoute, TimeValue.NEG_ONE_MILLISECONDS, PoolReusePolicy.LIFO, null, null);
     }
 
     public boolean isShutdown() {
@@ -127,6 +141,7 @@ public class LaxConnPool<T, C extends ModalCloseable> implements ManagedConnPool
                     timeToLive,
                     policy,
                     this,
+                    disposalCallback,
                     connPoolListener);
             routePool = routeToPool.putIfAbsent(route, newRoutePool);
             if (routePool == null) {
@@ -344,8 +359,9 @@ public class LaxConnPool<T, C extends ModalCloseable> implements ManagedConnPool
         private final T route;
         private final TimeValue timeToLive;
         private final PoolReusePolicy policy;
-        private final ConnPoolStats<T> connPoolStats;
+        private final Callback<C> disposalCallback;
         private final ConnPoolListener<T> connPoolListener;
+        private final ConnPoolStats<T> connPoolStats;
         private final ConcurrentMap<PoolEntry<T, C>, Boolean> leased;
         private final Deque<AtomicMarkableReference<PoolEntry<T, C>>> available;
         private final Deque<LeaseRequest<T, C>> pending;
@@ -361,12 +377,14 @@ public class LaxConnPool<T, C extends ModalCloseable> implements ManagedConnPool
                 final TimeValue timeToLive,
                 final PoolReusePolicy policy,
                 final ConnPoolStats<T> connPoolStats,
+                final Callback<C> disposalCallback,
                 final ConnPoolListener<T> connPoolListener) {
             super();
             this.route = route;
             this.timeToLive = timeToLive;
             this.policy = policy;
             this.connPoolStats = connPoolStats;
+            this.disposalCallback = disposalCallback;
             this.connPoolListener = connPoolListener;
             this.leased = new ConcurrentHashMap<>();
             this.available = new ConcurrentLinkedDeque<>();
@@ -401,7 +419,7 @@ public class LaxConnPool<T, C extends ModalCloseable> implements ManagedConnPool
                 prev = allocated.get();
                 next = (prev<poolmax)? prev+1 : prev;
             } while (!allocated.compareAndSet(prev, next));
-            return (prev < next)? new PoolEntry<T,C>(route, timeToLive) : null;
+            return (prev < next)? new PoolEntry<T,C>(route, timeToLive, disposalCallback) : null;
         }
 
         private void deallocatePoolEntry() {
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/pool/PoolEntry.java b/httpcore5/src/main/java/org/apache/hc/core5/pool/PoolEntry.java
index 60c11d7..48b292f 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/pool/PoolEntry.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/pool/PoolEntry.java
@@ -28,6 +28,7 @@ package org.apache.hc.core5.pool;
 
 import java.util.concurrent.atomic.AtomicReference;
 
+import org.apache.hc.core5.function.Callback;
 import org.apache.hc.core5.function.Supplier;
 import org.apache.hc.core5.io.CloseMode;
 import org.apache.hc.core5.io.ModalCloseable;
@@ -52,6 +53,7 @@ public final class PoolEntry<T, C extends ModalCloseable> {
     private final T route;
     private final TimeValue timeToLive;
     private final AtomicReference<C> connRef;
+    private final Callback<C> disposalCallback;
     private final Supplier<Long> currentTimeSupplier;
 
     private volatile Object state;
@@ -60,16 +62,30 @@ public final class PoolEntry<T, C extends ModalCloseable> {
     private volatile Deadline expiryDeadline = Deadline.MIN_VALUE;
     private volatile Deadline validityDeadline = Deadline.MIN_VALUE;
 
-    PoolEntry(final T route, final TimeValue timeToLive, final Supplier<Long> currentTimeSupplier) {
+    PoolEntry(final T route, final TimeValue timeToLive, final Callback<C> disposalCallback,
+              final Supplier<Long> currentTimeSupplier) {
         super();
         this.route = Args.notNull(route, "Route");
         this.timeToLive = TimeValue.defaultsToNegativeOneMillisecond(timeToLive);
         this.connRef = new AtomicReference<>(null);
+        this.disposalCallback = disposalCallback;
         this.currentTimeSupplier = currentTimeSupplier;
     }
 
-    long getCurrentTime() {
-        return currentTimeSupplier != null ? currentTimeSupplier.get() : System.currentTimeMillis();
+    PoolEntry(final T route, final TimeValue timeToLive, final Supplier<Long> currentTimeSupplier) {
+        this(route, timeToLive, null, currentTimeSupplier);
+    }
+
+    /**
+     * Creates new {@code PoolEntry} instance.
+     *
+     * @param route route to the opposite endpoint.
+     * @param timeToLive maximum time to live. May be zero if the connection
+     *   does not have an expiry deadline.
+     * @param disposalCallback callback invoked before connection disposal.
+     */
+    public PoolEntry(final T route, final TimeValue timeToLive, final Callback<C> disposalCallback) {
+        this(route, timeToLive, disposalCallback, null);
     }
 
     /**
@@ -80,13 +96,17 @@ public final class PoolEntry<T, C extends ModalCloseable> {
      *   does not have an expiry deadline.
      */
     public PoolEntry(final T route, final TimeValue timeToLive) {
-        this(route, timeToLive, null);
+        this(route, timeToLive, null, null);
     }
 
     public PoolEntry(final T route) {
         this(route, null);
     }
 
+    long getCurrentTime() {
+        return currentTimeSupplier != null ? currentTimeSupplier.get() : System.currentTimeMillis();
+    }
+
     public T getRoute() {
         return this.route;
     }
@@ -148,7 +168,11 @@ public final class PoolEntry<T, C extends ModalCloseable> {
             this.updated = 0;
             this.expiryDeadline = Deadline.MIN_VALUE;
             this.validityDeadline = Deadline.MIN_VALUE;
-            connection.close(closeMode);
+            if (this.disposalCallback != null) {
+                this.disposalCallback.execute(connection);
+            } else {
+                connection.close(closeMode);
+            }
         }
     }
 
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/pool/StrictConnPool.java b/httpcore5/src/main/java/org/apache/hc/core5/pool/StrictConnPool.java
index 1b9e8b2..8d55c00 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/pool/StrictConnPool.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/pool/StrictConnPool.java
@@ -66,8 +66,9 @@ import org.apache.hc.core5.util.Timeout;
 public class StrictConnPool<T, C extends ModalCloseable> implements ManagedConnPool<T, C> {
 
     private final TimeValue timeToLive;
-    private final ConnPoolListener<T> connPoolListener;
     private final PoolReusePolicy policy;
+    private final Callback<C> disposalCallback;
+    private final ConnPoolListener<T> connPoolListener;
     private final Map<T, PerRoutePool<T, C>> routeToPool;
     private final LinkedList<LeaseRequest<T, C>> leasingRequests;
     private final Set<PoolEntry<T, C>> leased;
@@ -88,13 +89,15 @@ public class StrictConnPool<T, C extends ModalCloseable> implements ManagedConnP
             final int maxTotal,
             final TimeValue timeToLive,
             final PoolReusePolicy policy,
+            final Callback<C> disposalCallback,
             final ConnPoolListener<T> connPoolListener) {
         super();
         Args.positive(defaultMaxPerRoute, "Max per route value");
         Args.positive(maxTotal, "Max total value");
         this.timeToLive = TimeValue.defaultsToNegativeOneMillisecond(timeToLive);
-        this.connPoolListener = connPoolListener;
         this.policy = policy != null ? policy : PoolReusePolicy.LIFO;
+        this.disposalCallback = disposalCallback;
+        this.connPoolListener = connPoolListener;
         this.routeToPool = new HashMap<>();
         this.leasingRequests = new LinkedList<>();
         this.leased = new HashSet<>();
@@ -107,6 +110,18 @@ public class StrictConnPool<T, C extends ModalCloseable> implements ManagedConnP
         this.maxTotal = maxTotal;
     }
 
+    /**
+     * @since 5.0
+     */
+    public StrictConnPool(
+            final int defaultMaxPerRoute,
+            final int maxTotal,
+            final TimeValue timeToLive,
+            final PoolReusePolicy policy,
+            final ConnPoolListener<T> connPoolListener) {
+        this(defaultMaxPerRoute, maxTotal, timeToLive, policy, null, connPoolListener);
+    }
+
     public StrictConnPool(final int defaultMaxPerRoute, final int maxTotal) {
         this(defaultMaxPerRoute, maxTotal, TimeValue.NEG_ONE_MILLISECONDS, PoolReusePolicy.LIFO, null);
     }
@@ -142,7 +157,7 @@ public class StrictConnPool<T, C extends ModalCloseable> implements ManagedConnP
     private PerRoutePool<T, C> getPool(final T route) {
         PerRoutePool<T, C> pool = this.routeToPool.get(route);
         if (pool == null) {
-            pool = new PerRoutePool<>(route);
+            pool = new PerRoutePool<>(route, this.disposalCallback);
             this.routeToPool.put(route, pool);
         }
         return pool;
@@ -704,10 +719,12 @@ public class StrictConnPool<T, C extends ModalCloseable> implements ManagedConnP
         private final T route;
         private final Set<PoolEntry<T, C>> leased;
         private final LinkedList<PoolEntry<T, C>> available;
+        private final Callback<C> disposalCallback;
 
-        PerRoutePool(final T route) {
+        PerRoutePool(final T route, final Callback<C> disposalCallback) {
             super();
             this.route = route;
+            this.disposalCallback = disposalCallback;
             this.leased = new HashSet<>();
             this.available = new LinkedList<>();
         }
@@ -771,7 +788,7 @@ public class StrictConnPool<T, C extends ModalCloseable> implements ManagedConnP
         }
 
         public PoolEntry<T, C> createEntry(final TimeValue timeToLive) {
-            final PoolEntry<T, C> entry = new PoolEntry<>(this.route, timeToLive);
+            final PoolEntry<T, C> entry = new PoolEntry<>(this.route, timeToLive, disposalCallback);
             this.leased.add(entry);
             return entry;
         }
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOSession.java b/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOSession.java
index 30317da..f74060e 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOSession.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOSession.java
@@ -31,7 +31,7 @@ import java.net.SocketAddress;
 import java.nio.channels.ByteChannel;
 import java.util.concurrent.locks.Lock;
 
-import org.apache.hc.core5.io.ModalCloseable;
+import org.apache.hc.core5.http.SocketModalCloseable;
 import org.apache.hc.core5.util.Identifiable;
 import org.apache.hc.core5.util.Timeout;
 
@@ -51,7 +51,7 @@ import org.apache.hc.core5.util.Timeout;
  *
  * @since 4.0
  */
-public interface IOSession extends ModalCloseable, Identifiable {
+public interface IOSession extends SocketModalCloseable, Identifiable {
 
     int ACTIVE       = 0;
     int CLOSING      = 1;


[httpcomponents-core] 01/02: Connection pools to close connections gracefully in case of an ordinary connection disposal

Posted by ol...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

olegk pushed a commit to branch HTTPCORE-596
in repository https://gitbox.apache.org/repos/asf/httpcomponents-core.git

commit f5bb9a7340980622f5684928578bafa066af3534
Author: Oleg Kalnichevski <ol...@apache.org>
AuthorDate: Sat Sep 7 11:55:57 2019 +0200

    Connection pools to close connections gracefully in case of an ordinary connection disposal
---
 .../org/apache/hc/core5/http/impl/bootstrap/HttpAsyncRequester.java     | 2 +-
 .../java/org/apache/hc/core5/http/impl/bootstrap/HttpRequester.java     | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/HttpAsyncRequester.java b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/HttpAsyncRequester.java
index c10a721..020a334 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/HttpAsyncRequester.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/HttpAsyncRequester.java
@@ -463,7 +463,7 @@ public class HttpAsyncRequester extends AsyncRequester implements ConnPoolContro
         public void releaseAndDiscard() {
             final PoolEntry<HttpHost, IOSession> poolEntry = poolEntryRef.getAndSet(null);
             if (poolEntry != null) {
-                poolEntry.discardConnection(CloseMode.IMMEDIATE);
+                poolEntry.discardConnection(CloseMode.GRACEFUL);
                 connPool.release(poolEntry, false);
             }
         }
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/HttpRequester.java b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/HttpRequester.java
index 11e3c1b..f6d78d6 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/HttpRequester.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/HttpRequester.java
@@ -484,7 +484,7 @@ public class HttpRequester implements ConnPoolControl<HttpHost>, ModalCloseable
         void discardConnection() {
             final PoolEntry<HttpHost, HttpClientConnection> poolEntry = poolEntryRef.getAndSet(null);
             if (poolEntry != null) {
-                poolEntry.discardConnection(CloseMode.IMMEDIATE);
+                poolEntry.discardConnection(CloseMode.GRACEFUL);
                 connPool.release(poolEntry, false);
             }
         }