1069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project/*
2069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/conn/tsccm/AbstractConnPool.java $
3069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * $Revision: 673450 $
4069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * $Date: 2008-07-02 10:35:05 -0700 (Wed, 02 Jul 2008) $
5069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
6069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * ====================================================================
7069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
8069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *  Licensed to the Apache Software Foundation (ASF) under one or more
9069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *  contributor license agreements.  See the NOTICE file distributed with
10069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *  this work for additional information regarding copyright ownership.
11069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *  The ASF licenses this file to You under the Apache License, Version 2.0
12069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *  (the "License"); you may not use this file except in compliance with
13069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *  the License.  You may obtain a copy of the License at
14069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
15069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
16069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
17069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *  Unless required by applicable law or agreed to in writing, software
18069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *  distributed under the License is distributed on an "AS IS" BASIS,
19069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *  See the License for the specific language governing permissions and
21069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *  limitations under the License.
22069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * ====================================================================
23069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
24069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * This software consists of voluntary contributions made by many
25069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * individuals on behalf of the Apache Software Foundation.  For more
26069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * information on the Apache Software Foundation, please see
27069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <http://www.apache.org/>.
28069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
29069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */
30069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
31069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectpackage org.apache.http.impl.conn.tsccm;
32069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
33069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport java.io.IOException;
34069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport java.lang.ref.Reference;
35069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport java.lang.ref.ReferenceQueue;
36069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport java.util.Set;
37069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport java.util.HashSet;
38069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport java.util.Iterator;
39069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport java.util.concurrent.TimeUnit;
40069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport java.util.concurrent.locks.Lock;
41069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport java.util.concurrent.locks.ReentrantLock;
42069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
43069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.commons.logging.Log;
44069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.commons.logging.LogFactory;
45069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.http.conn.ConnectionPoolTimeoutException;
46069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.http.conn.OperatedClientConnection;
47069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.http.conn.routing.HttpRoute;
48069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.http.impl.conn.IdleConnectionHandler;
49069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
50069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
51069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project/**
52069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * An abstract connection pool.
53069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * It is used by the {@link ThreadSafeClientConnManager}.
54069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * The abstract pool includes a {@link #poolLock}, which is used to
55069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * synchronize access to the internal pool datastructures.
56069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Don't use <code>synchronized</code> for that purpose!
57d42abb2fd917184764daf22f5f299e848b8701d7Narayan Kamath *
58d42abb2fd917184764daf22f5f299e848b8701d7Narayan Kamath * @deprecated Please use {@link java.net.URL#openConnection} instead.
59d42abb2fd917184764daf22f5f299e848b8701d7Narayan Kamath *     Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a>
60d42abb2fd917184764daf22f5f299e848b8701d7Narayan Kamath *     for further details.
61069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */
62d42abb2fd917184764daf22f5f299e848b8701d7Narayan Kamath@Deprecated
63069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectpublic abstract class AbstractConnPool implements RefQueueHandler {
64069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
65069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private final Log log = LogFactory.getLog(getClass());
66069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
67069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
68069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * The global lock for this pool.
69069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
70069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    protected final Lock poolLock;
71069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
72069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
73069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
74069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * References to issued connections.
75069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Objects in this set are of class
76069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * {@link BasicPoolEntryRef BasicPoolEntryRef},
77069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * and point to the pool entry for the issued connection.
78069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * GCed connections are detected by the missing pool entries.
79069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
80069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    protected Set<BasicPoolEntryRef> issuedConnections;
81069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
82069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /** The handler for idle connections. */
83069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    protected IdleConnectionHandler idleConnHandler;
84069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
85069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /** The current total number of connections. */
86069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    protected int numConnections;
87069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
88069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
89069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * A reference queue to track loss of pool entries to GC.
90069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * The same queue is used to track loss of the connection manager,
91069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * so we cannot specialize the type.
92069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
93069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    protected ReferenceQueue<Object> refQueue;
94069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
95069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /** A worker (thread) to track loss of pool entries to GC. */
96069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private RefQueueWorker refWorker;
97069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
98069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
99069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /** Indicates whether this pool is shut down. */
100069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    protected volatile boolean isShutDown;
101069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
102069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
103069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Creates a new connection pool.
104069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
105069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    protected AbstractConnPool() {
106069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        issuedConnections = new HashSet<BasicPoolEntryRef>();
107069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        idleConnHandler = new IdleConnectionHandler();
108069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
109069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        boolean fair = false; //@@@ check parameters to decide
110069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        poolLock = new ReentrantLock(fair);
111069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
112069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
113069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
114069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
115069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Enables connection garbage collection (GC).
116069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * This method must be called immediately after creating the
117069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * connection pool. It is not possible to enable connection GC
118069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * after pool entries have been created. Neither is it possible
119069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * to disable connection GC.
120069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
121069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @throws IllegalStateException
122069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *         if connection GC is already enabled, or if it cannot be
123069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *         enabled because there already are pool entries
124069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
125069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public void enableConnectionGC()
126069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        throws IllegalStateException {
127069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
128069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (refQueue != null) {
129069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw new IllegalStateException("Connection GC already enabled.");
130069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
131069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        poolLock.lock();
132069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        try {
133069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (numConnections > 0) { //@@@ is this check sufficient?
134069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                throw new IllegalStateException("Pool already in use.");
135069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
136069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } finally {
137069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            poolLock.unlock();
138069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
139069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
140069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        refQueue  = new ReferenceQueue<Object>();
141069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        refWorker = new RefQueueWorker(refQueue, this);
142069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        Thread t = new Thread(refWorker); //@@@ use a thread factory
143069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        t.setDaemon(true);
144069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        t.setName("RefQueueWorker@" + this);
145069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        t.start();
146069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
147069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
148069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
149069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
150069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Obtains a pool entry with a connection within the given timeout.
151069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
152069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param route     the route for which to get the connection
153069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param timeout   the timeout, 0 or negative for no timeout
154069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param tunit     the unit for the <code>timeout</code>,
155069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *                  may be <code>null</code> only if there is no timeout
156069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
157069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @return  pool entry holding a connection for the route
158069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
159069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @throws ConnectionPoolTimeoutException
160069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *         if the timeout expired
161069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @throws InterruptedException
162069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *         if the calling thread was interrupted
163069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
164069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public final
165069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        BasicPoolEntry getEntry(
166069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                HttpRoute route,
167069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                Object state,
168069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                long timeout,
169069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                TimeUnit tunit)
170069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    throws ConnectionPoolTimeoutException, InterruptedException {
171069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return requestPoolEntry(route, state).getPoolEntry(timeout, tunit);
172069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
173069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
174069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
175069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Returns a new {@link PoolEntryRequest}, from which a {@link BasicPoolEntry}
176069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * can be obtained, or the request can be aborted.
177069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
178069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public abstract PoolEntryRequest requestPoolEntry(HttpRoute route, Object state);
179069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
180069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
181069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
182069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Returns an entry into the pool.
183069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * The connection of the entry is expected to be in a suitable state,
184069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * either open and re-usable, or closed. The pool will not make any
185069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * attempt to determine whether it can be re-used or not.
186069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
187069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param entry     the entry for the connection to release
188069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param reusable  <code>true</code> if the entry is deemed
189069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *                  reusable, <code>false</code> otherwise.
190069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param validDuration The duration that the entry should remain free and reusable.
191069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param timeUnit The unit of time the duration is measured in.
192069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
193069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public abstract void freeEntry(BasicPoolEntry entry, boolean reusable, long validDuration, TimeUnit timeUnit)
194069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        ;
195069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
196069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
197069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
198069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    // non-javadoc, see interface RefQueueHandler
199069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project// BEGIN android-changed
200069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public void handleReference(Reference ref) {
201069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project// END android-changed
202069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        poolLock.lock();
203069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        try {
204069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
205069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (ref instanceof BasicPoolEntryRef) {
206069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                // check if the GCed pool entry was still in use
207069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                //@@@ find a way to detect this without lookup
208069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                //@@@ flag in the BasicPoolEntryRef, to be reset when freed?
209069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                final boolean lost = issuedConnections.remove(ref);
210069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                if (lost) {
211069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    final HttpRoute route =
212069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        ((BasicPoolEntryRef)ref).getRoute();
213069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    if (log.isDebugEnabled()) {
214069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        log.debug("Connection garbage collected. " + route);
215069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    }
216069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    handleLostEntry(route);
217069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                }
218069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
219069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
220069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } finally {
221069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            poolLock.unlock();
222069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
223069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
224069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
225069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
226069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
227069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Handles cleaning up for a lost pool entry with the given route.
228069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * A lost pool entry corresponds to a connection that was
229069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * garbage collected instead of being properly released.
230069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
231069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param route     the route of the pool entry that was lost
232069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
233069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    protected abstract void handleLostEntry(HttpRoute route)
234069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        ;
235069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
236069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
237069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
238069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Closes idle connections.
239069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
240069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param idletime  the time the connections should have been idle
241069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *                  in order to be closed now
242069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param tunit     the unit for the <code>idletime</code>
243069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
244069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public void closeIdleConnections(long idletime, TimeUnit tunit) {
245069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
246069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // idletime can be 0 or negative, no problem there
247069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (tunit == null) {
248069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw new IllegalArgumentException("Time unit must not be null.");
249069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
250069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
251069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        poolLock.lock();
252069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        try {
253069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            idleConnHandler.closeIdleConnections(tunit.toMillis(idletime));
254069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } finally {
255069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            poolLock.unlock();
256069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
257069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
258069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
259069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public void closeExpiredConnections() {
260069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        poolLock.lock();
261069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        try {
262069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            idleConnHandler.closeExpiredConnections();
263069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } finally {
264069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            poolLock.unlock();
265069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
266069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
267069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
268069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
269069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    //@@@ revise this cleanup stuff (closeIdle+deleteClosed), it's not good
270069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
271069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
272069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Deletes all entries for closed connections.
273069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
274069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public abstract void deleteClosedConnections()
275069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        ;
276069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
277069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
278069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
279069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Shuts down this pool and all associated resources.
280069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Overriding methods MUST call the implementation here!
281069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
282069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public void shutdown() {
283069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
284069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        poolLock.lock();
285069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        try {
286069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
287069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (isShutDown)
288069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                return;
289069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
290069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            // no point in monitoring GC anymore
291069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (refWorker != null)
292069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                refWorker.shutdown();
293069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
294069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            // close all connections that are issued to an application
295069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            Iterator<BasicPoolEntryRef> iter = issuedConnections.iterator();
296069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            while (iter.hasNext()) {
297069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                BasicPoolEntryRef per = iter.next();
298069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                iter.remove();
299069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                BasicPoolEntry entry = per.get();
300069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                if (entry != null) {
301069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    closeConnection(entry.getConnection());
302069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                }
303069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
304069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
305069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            // remove all references to connections
306069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            //@@@ use this for shutting them down instead?
307069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            idleConnHandler.removeAll();
308069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
309069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            isShutDown = true;
310069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
311069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } finally {
312069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            poolLock.unlock();
313069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
314069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
315069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
316069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
317069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
318069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Closes a connection from this pool.
319069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
320069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param conn      the connection to close, or <code>null</code>
321069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
322069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    protected void closeConnection(final OperatedClientConnection conn) {
323069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (conn != null) {
324069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            try {
325069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                conn.close();
326069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            } catch (IOException ex) {
327069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                log.debug("I/O error closing connection", ex);
328069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
329069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
330069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
331069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
332069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
333069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
334069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
335069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
336069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project} // class AbstractConnPool
337069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
338