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