Wed, 31 Dec 2014 07:22:50 +0100
Correct previous dual key logic pending first delivery installment.
michael@0 | 1 | /* |
michael@0 | 2 | * ==================================================================== |
michael@0 | 3 | * |
michael@0 | 4 | * Licensed to the Apache Software Foundation (ASF) under one or more |
michael@0 | 5 | * contributor license agreements. See the NOTICE file distributed with |
michael@0 | 6 | * this work for additional information regarding copyright ownership. |
michael@0 | 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 |
michael@0 | 8 | * (the "License"); you may not use this file except in compliance with |
michael@0 | 9 | * the License. You may obtain a copy of the License at |
michael@0 | 10 | * |
michael@0 | 11 | * http://www.apache.org/licenses/LICENSE-2.0 |
michael@0 | 12 | * |
michael@0 | 13 | * Unless required by applicable law or agreed to in writing, software |
michael@0 | 14 | * distributed under the License is distributed on an "AS IS" BASIS, |
michael@0 | 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
michael@0 | 16 | * See the License for the specific language governing permissions and |
michael@0 | 17 | * limitations under the License. |
michael@0 | 18 | * ==================================================================== |
michael@0 | 19 | * |
michael@0 | 20 | * This software consists of voluntary contributions made by many |
michael@0 | 21 | * individuals on behalf of the Apache Software Foundation. For more |
michael@0 | 22 | * information on the Apache Software Foundation, please see |
michael@0 | 23 | * <http://www.apache.org/>. |
michael@0 | 24 | * |
michael@0 | 25 | */ |
michael@0 | 26 | |
michael@0 | 27 | package ch.boye.httpclientandroidlib.impl.conn.tsccm; |
michael@0 | 28 | |
michael@0 | 29 | import java.io.IOException; |
michael@0 | 30 | import java.lang.ref.Reference; |
michael@0 | 31 | import java.lang.ref.ReferenceQueue; |
michael@0 | 32 | import java.util.Set; |
michael@0 | 33 | import java.util.HashSet; |
michael@0 | 34 | import java.util.Iterator; |
michael@0 | 35 | import java.util.concurrent.TimeUnit; |
michael@0 | 36 | import java.util.concurrent.locks.Lock; |
michael@0 | 37 | import java.util.concurrent.locks.ReentrantLock; |
michael@0 | 38 | |
michael@0 | 39 | import ch.boye.httpclientandroidlib.annotation.GuardedBy; |
michael@0 | 40 | |
michael@0 | 41 | import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog; |
michael@0 | 42 | /* LogFactory removed by HttpClient for Android script. */ |
michael@0 | 43 | import ch.boye.httpclientandroidlib.conn.ConnectionPoolTimeoutException; |
michael@0 | 44 | import ch.boye.httpclientandroidlib.conn.OperatedClientConnection; |
michael@0 | 45 | import ch.boye.httpclientandroidlib.conn.routing.HttpRoute; |
michael@0 | 46 | import ch.boye.httpclientandroidlib.impl.conn.IdleConnectionHandler; |
michael@0 | 47 | |
michael@0 | 48 | /** |
michael@0 | 49 | * An abstract connection pool. |
michael@0 | 50 | * It is used by the {@link ThreadSafeClientConnManager}. |
michael@0 | 51 | * The abstract pool includes a {@link #poolLock}, which is used to |
michael@0 | 52 | * synchronize access to the internal pool datastructures. |
michael@0 | 53 | * Don't use <code>synchronized</code> for that purpose! |
michael@0 | 54 | * |
michael@0 | 55 | * @since 4.0 |
michael@0 | 56 | */ |
michael@0 | 57 | |
michael@0 | 58 | @Deprecated |
michael@0 | 59 | public abstract class AbstractConnPool implements RefQueueHandler { |
michael@0 | 60 | |
michael@0 | 61 | public HttpClientAndroidLog log; |
michael@0 | 62 | |
michael@0 | 63 | /** |
michael@0 | 64 | * The global lock for this pool. |
michael@0 | 65 | */ |
michael@0 | 66 | protected final Lock poolLock; |
michael@0 | 67 | |
michael@0 | 68 | /** References to issued connections */ |
michael@0 | 69 | @GuardedBy("poolLock") |
michael@0 | 70 | protected Set<BasicPoolEntry> leasedConnections; |
michael@0 | 71 | |
michael@0 | 72 | /** The current total number of connections. */ |
michael@0 | 73 | @GuardedBy("poolLock") |
michael@0 | 74 | protected int numConnections; |
michael@0 | 75 | |
michael@0 | 76 | /** Indicates whether this pool is shut down. */ |
michael@0 | 77 | protected volatile boolean isShutDown; |
michael@0 | 78 | |
michael@0 | 79 | protected Set<BasicPoolEntryRef> issuedConnections; |
michael@0 | 80 | |
michael@0 | 81 | protected ReferenceQueue<Object> refQueue; |
michael@0 | 82 | |
michael@0 | 83 | protected IdleConnectionHandler idleConnHandler; |
michael@0 | 84 | |
michael@0 | 85 | /** |
michael@0 | 86 | * Creates a new connection pool. |
michael@0 | 87 | */ |
michael@0 | 88 | protected AbstractConnPool() { |
michael@0 | 89 | super(); |
michael@0 | 90 | this.log = new HttpClientAndroidLog(getClass()); |
michael@0 | 91 | this.leasedConnections = new HashSet<BasicPoolEntry>(); |
michael@0 | 92 | this.idleConnHandler = new IdleConnectionHandler(); |
michael@0 | 93 | this.poolLock = new ReentrantLock(); |
michael@0 | 94 | } |
michael@0 | 95 | |
michael@0 | 96 | public void enableConnectionGC() |
michael@0 | 97 | throws IllegalStateException { |
michael@0 | 98 | } |
michael@0 | 99 | |
michael@0 | 100 | /** |
michael@0 | 101 | * Obtains a pool entry with a connection within the given timeout. |
michael@0 | 102 | * |
michael@0 | 103 | * @param route the route for which to get the connection |
michael@0 | 104 | * @param timeout the timeout, 0 or negative for no timeout |
michael@0 | 105 | * @param tunit the unit for the <code>timeout</code>, |
michael@0 | 106 | * may be <code>null</code> only if there is no timeout |
michael@0 | 107 | * |
michael@0 | 108 | * @return pool entry holding a connection for the route |
michael@0 | 109 | * |
michael@0 | 110 | * @throws ConnectionPoolTimeoutException |
michael@0 | 111 | * if the timeout expired |
michael@0 | 112 | * @throws InterruptedException |
michael@0 | 113 | * if the calling thread was interrupted |
michael@0 | 114 | */ |
michael@0 | 115 | public final |
michael@0 | 116 | BasicPoolEntry getEntry( |
michael@0 | 117 | HttpRoute route, |
michael@0 | 118 | Object state, |
michael@0 | 119 | long timeout, |
michael@0 | 120 | TimeUnit tunit) |
michael@0 | 121 | throws ConnectionPoolTimeoutException, InterruptedException { |
michael@0 | 122 | return requestPoolEntry(route, state).getPoolEntry(timeout, tunit); |
michael@0 | 123 | } |
michael@0 | 124 | |
michael@0 | 125 | /** |
michael@0 | 126 | * Returns a new {@link PoolEntryRequest}, from which a {@link BasicPoolEntry} |
michael@0 | 127 | * can be obtained, or the request can be aborted. |
michael@0 | 128 | */ |
michael@0 | 129 | public abstract PoolEntryRequest requestPoolEntry(HttpRoute route, Object state); |
michael@0 | 130 | |
michael@0 | 131 | |
michael@0 | 132 | /** |
michael@0 | 133 | * Returns an entry into the pool. |
michael@0 | 134 | * The connection of the entry is expected to be in a suitable state, |
michael@0 | 135 | * either open and re-usable, or closed. The pool will not make any |
michael@0 | 136 | * attempt to determine whether it can be re-used or not. |
michael@0 | 137 | * |
michael@0 | 138 | * @param entry the entry for the connection to release |
michael@0 | 139 | * @param reusable <code>true</code> if the entry is deemed |
michael@0 | 140 | * reusable, <code>false</code> otherwise. |
michael@0 | 141 | * @param validDuration The duration that the entry should remain free and reusable. |
michael@0 | 142 | * @param timeUnit The unit of time the duration is measured in. |
michael@0 | 143 | */ |
michael@0 | 144 | public abstract void freeEntry(BasicPoolEntry entry, boolean reusable, long validDuration, TimeUnit timeUnit) |
michael@0 | 145 | ; |
michael@0 | 146 | |
michael@0 | 147 | public void handleReference(Reference<?> ref) { |
michael@0 | 148 | } |
michael@0 | 149 | |
michael@0 | 150 | protected abstract void handleLostEntry(HttpRoute route); |
michael@0 | 151 | |
michael@0 | 152 | /** |
michael@0 | 153 | * Closes idle connections. |
michael@0 | 154 | * |
michael@0 | 155 | * @param idletime the time the connections should have been idle |
michael@0 | 156 | * in order to be closed now |
michael@0 | 157 | * @param tunit the unit for the <code>idletime</code> |
michael@0 | 158 | */ |
michael@0 | 159 | public void closeIdleConnections(long idletime, TimeUnit tunit) { |
michael@0 | 160 | |
michael@0 | 161 | // idletime can be 0 or negative, no problem there |
michael@0 | 162 | if (tunit == null) { |
michael@0 | 163 | throw new IllegalArgumentException("Time unit must not be null."); |
michael@0 | 164 | } |
michael@0 | 165 | |
michael@0 | 166 | poolLock.lock(); |
michael@0 | 167 | try { |
michael@0 | 168 | idleConnHandler.closeIdleConnections(tunit.toMillis(idletime)); |
michael@0 | 169 | } finally { |
michael@0 | 170 | poolLock.unlock(); |
michael@0 | 171 | } |
michael@0 | 172 | } |
michael@0 | 173 | |
michael@0 | 174 | public void closeExpiredConnections() { |
michael@0 | 175 | poolLock.lock(); |
michael@0 | 176 | try { |
michael@0 | 177 | idleConnHandler.closeExpiredConnections(); |
michael@0 | 178 | } finally { |
michael@0 | 179 | poolLock.unlock(); |
michael@0 | 180 | } |
michael@0 | 181 | } |
michael@0 | 182 | |
michael@0 | 183 | |
michael@0 | 184 | /** |
michael@0 | 185 | * Deletes all entries for closed connections. |
michael@0 | 186 | */ |
michael@0 | 187 | public abstract void deleteClosedConnections(); |
michael@0 | 188 | |
michael@0 | 189 | /** |
michael@0 | 190 | * Shuts down this pool and all associated resources. |
michael@0 | 191 | * Overriding methods MUST call the implementation here! |
michael@0 | 192 | */ |
michael@0 | 193 | public void shutdown() { |
michael@0 | 194 | |
michael@0 | 195 | poolLock.lock(); |
michael@0 | 196 | try { |
michael@0 | 197 | |
michael@0 | 198 | if (isShutDown) |
michael@0 | 199 | return; |
michael@0 | 200 | |
michael@0 | 201 | // close all connections that are issued to an application |
michael@0 | 202 | Iterator<BasicPoolEntry> iter = leasedConnections.iterator(); |
michael@0 | 203 | while (iter.hasNext()) { |
michael@0 | 204 | BasicPoolEntry entry = iter.next(); |
michael@0 | 205 | iter.remove(); |
michael@0 | 206 | closeConnection(entry.getConnection()); |
michael@0 | 207 | } |
michael@0 | 208 | idleConnHandler.removeAll(); |
michael@0 | 209 | |
michael@0 | 210 | isShutDown = true; |
michael@0 | 211 | |
michael@0 | 212 | } finally { |
michael@0 | 213 | poolLock.unlock(); |
michael@0 | 214 | } |
michael@0 | 215 | } |
michael@0 | 216 | |
michael@0 | 217 | |
michael@0 | 218 | /** |
michael@0 | 219 | * Closes a connection from this pool. |
michael@0 | 220 | * |
michael@0 | 221 | * @param conn the connection to close, or <code>null</code> |
michael@0 | 222 | */ |
michael@0 | 223 | protected void closeConnection(final OperatedClientConnection conn) { |
michael@0 | 224 | if (conn != null) { |
michael@0 | 225 | try { |
michael@0 | 226 | conn.close(); |
michael@0 | 227 | } catch (IOException ex) { |
michael@0 | 228 | log.debug("I/O error closing connection", ex); |
michael@0 | 229 | } |
michael@0 | 230 | } |
michael@0 | 231 | } |
michael@0 | 232 | |
michael@0 | 233 | } // class AbstractConnPool |
michael@0 | 234 |