Home | History | Annotate | Download | only in tsccm
      1 /*
      2  * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/conn/tsccm/RouteSpecificPool.java $
      3  * $Revision: 677240 $
      4  * $Date: 2008-07-16 04:25:47 -0700 (Wed, 16 Jul 2008) $
      5  *
      6  * ====================================================================
      7  *
      8  *  Licensed to the Apache Software Foundation (ASF) under one or more
      9  *  contributor license agreements.  See the NOTICE file distributed with
     10  *  this work for additional information regarding copyright ownership.
     11  *  The ASF licenses this file to You under the Apache License, Version 2.0
     12  *  (the "License"); you may not use this file except in compliance with
     13  *  the License.  You may obtain a copy of the License at
     14  *
     15  *      http://www.apache.org/licenses/LICENSE-2.0
     16  *
     17  *  Unless required by applicable law or agreed to in writing, software
     18  *  distributed under the License is distributed on an "AS IS" BASIS,
     19  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     20  *  See the License for the specific language governing permissions and
     21  *  limitations under the License.
     22  * ====================================================================
     23  *
     24  * This software consists of voluntary contributions made by many
     25  * individuals on behalf of the Apache Software Foundation.  For more
     26  * information on the Apache Software Foundation, please see
     27  * <http://www.apache.org/>.
     28  *
     29  */
     30 
     31 package org.apache.http.impl.conn.tsccm;
     32 
     33 import java.io.IOException;
     34 import java.util.ListIterator;
     35 import java.util.Queue;
     36 import java.util.LinkedList;
     37 
     38 import org.apache.commons.logging.Log;
     39 import org.apache.commons.logging.LogFactory;
     40 import org.apache.http.conn.OperatedClientConnection;
     41 import org.apache.http.conn.routing.HttpRoute;
     42 import org.apache.http.util.LangUtils;
     43 
     44 
     45 /**
     46  * A connection sub-pool for a specific route, used by {@link ConnPoolByRoute}.
     47  * The methods in this class are unsynchronized. It is expected that the
     48  * containing pool takes care of synchronization.
     49  *
     50  * @deprecated Please use {@link java.net.URL#openConnection} instead.
     51  *     Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a>
     52  *     for further details.
     53  */
     54 @Deprecated
     55 public class RouteSpecificPool {
     56 
     57     private final Log log = LogFactory.getLog(getClass());
     58 
     59     /** The route this pool is for. */
     60     protected final HttpRoute route;
     61 
     62     /** the maximum number of entries allowed for this pool */
     63     protected final int maxEntries;
     64 
     65     /**
     66      * The list of free entries.
     67      * This list is managed LIFO, to increase idle times and
     68      * allow for closing connections that are not really needed.
     69      */
     70     protected final LinkedList<BasicPoolEntry> freeEntries;
     71 
     72     /** The list of threads waiting for this pool. */
     73     protected final Queue<WaitingThread> waitingThreads;
     74 
     75     /** The number of created entries. */
     76     protected int numEntries;
     77 
     78 
     79     /**
     80      * Creates a new route-specific pool.
     81      *
     82      * @param route the route for which to pool
     83      * @param maxEntries the maximum number of entries allowed for this pool
     84      */
     85     public RouteSpecificPool(HttpRoute route, int maxEntries) {
     86         this.route = route;
     87         this.maxEntries = maxEntries;
     88         this.freeEntries = new LinkedList<BasicPoolEntry>();
     89         this.waitingThreads = new LinkedList<WaitingThread>();
     90         this.numEntries = 0;
     91     }
     92 
     93 
     94     /**
     95      * Obtains the route for which this pool is specific.
     96      *
     97      * @return  the route
     98      */
     99     public final HttpRoute getRoute() {
    100         return route;
    101     }
    102 
    103 
    104     /**
    105      * Obtains the maximum number of entries allowed for this pool.
    106      *
    107      * @return  the max entry number
    108      */
    109     public final int getMaxEntries() {
    110         return maxEntries;
    111     }
    112 
    113 
    114     /**
    115      * Indicates whether this pool is unused.
    116      * A pool is unused if there is neither an entry nor a waiting thread.
    117      * All entries count, not only the free but also the allocated ones.
    118      *
    119      * @return  <code>true</code> if this pool is unused,
    120      *          <code>false</code> otherwise
    121      */
    122     public boolean isUnused() {
    123         return (numEntries < 1) && waitingThreads.isEmpty();
    124     }
    125 
    126 
    127     /**
    128      * Return remaining capacity of this pool
    129      *
    130      * @return capacity
    131      */
    132     public int getCapacity() {
    133         return maxEntries - numEntries;
    134     }
    135 
    136 
    137     /**
    138      * Obtains the number of entries.
    139      * This includes not only the free entries, but also those that
    140      * have been created and are currently issued to an application.
    141      *
    142      * @return  the number of entries for the route of this pool
    143      */
    144     public final int getEntryCount() {
    145         return numEntries;
    146     }
    147 
    148 
    149     /**
    150      * Obtains a free entry from this pool, if one is available.
    151      *
    152      * @return an available pool entry, or <code>null</code> if there is none
    153      */
    154     public BasicPoolEntry allocEntry(final Object state) {
    155         if (!freeEntries.isEmpty()) {
    156             ListIterator<BasicPoolEntry> it = freeEntries.listIterator(freeEntries.size());
    157             while (it.hasPrevious()) {
    158                 BasicPoolEntry entry = it.previous();
    159                 if (LangUtils.equals(state, entry.getState())) {
    160                     it.remove();
    161                     return entry;
    162                 }
    163             }
    164         }
    165         if (!freeEntries.isEmpty()) {
    166             BasicPoolEntry entry = freeEntries.remove();
    167             entry.setState(null);
    168             OperatedClientConnection conn = entry.getConnection();
    169             try {
    170                 conn.close();
    171             } catch (IOException ex) {
    172                 log.debug("I/O error closing connection", ex);
    173             }
    174             return entry;
    175         }
    176         return null;
    177     }
    178 
    179 
    180     /**
    181      * Returns an allocated entry to this pool.
    182      *
    183      * @param entry     the entry obtained from {@link #allocEntry allocEntry}
    184      *                  or presented to {@link #createdEntry createdEntry}
    185      */
    186     public void freeEntry(BasicPoolEntry entry) {
    187 
    188         if (numEntries < 1) {
    189             throw new IllegalStateException
    190                 ("No entry created for this pool. " + route);
    191         }
    192         if (numEntries <= freeEntries.size()) {
    193             throw new IllegalStateException
    194                 ("No entry allocated from this pool. " + route);
    195         }
    196         freeEntries.add(entry);
    197     }
    198 
    199 
    200     /**
    201      * Indicates creation of an entry for this pool.
    202      * The entry will <i>not</i> be added to the list of free entries,
    203      * it is only recognized as belonging to this pool now. It can then
    204      * be passed to {@link #freeEntry freeEntry}.
    205      *
    206      * @param entry     the entry that was created for this pool
    207      */
    208     public void createdEntry(BasicPoolEntry entry) {
    209 
    210         if (!route.equals(entry.getPlannedRoute())) {
    211             throw new IllegalArgumentException
    212                 ("Entry not planned for this pool." +
    213                  "\npool: " + route +
    214                  "\nplan: " + entry.getPlannedRoute());
    215         }
    216 
    217         numEntries++;
    218     }
    219 
    220 
    221     /**
    222      * Deletes an entry from this pool.
    223      * Only entries that are currently free in this pool can be deleted.
    224      * Allocated entries can not be deleted.
    225      *
    226      * @param entry     the entry to delete from this pool
    227      *
    228      * @return  <code>true</code> if the entry was found and deleted, or
    229      *          <code>false</code> if the entry was not found
    230      */
    231     public boolean deleteEntry(BasicPoolEntry entry) {
    232 
    233         final boolean found = freeEntries.remove(entry);
    234         if (found)
    235             numEntries--;
    236         return found;
    237     }
    238 
    239 
    240     /**
    241      * Forgets about an entry from this pool.
    242      * This method is used to indicate that an entry
    243      * {@link #allocEntry allocated}
    244      * from this pool has been lost and will not be returned.
    245      */
    246     public void dropEntry() {
    247         if (numEntries < 1) {
    248             throw new IllegalStateException
    249                 ("There is no entry that could be dropped.");
    250         }
    251         numEntries--;
    252     }
    253 
    254 
    255     /**
    256      * Adds a waiting thread.
    257      * This pool makes no attempt to match waiting threads with pool entries.
    258      * It is the caller's responsibility to check that there is no entry
    259      * before adding a waiting thread.
    260      *
    261      * @param wt        the waiting thread
    262      */
    263     public void queueThread(WaitingThread wt) {
    264         if (wt == null) {
    265             throw new IllegalArgumentException
    266                 ("Waiting thread must not be null.");
    267         }
    268         this.waitingThreads.add(wt);
    269     }
    270 
    271 
    272     /**
    273      * Checks whether there is a waiting thread in this pool.
    274      *
    275      * @return  <code>true</code> if there is a waiting thread,
    276      *          <code>false</code> otherwise
    277      */
    278     public boolean hasThread() {
    279         return !this.waitingThreads.isEmpty();
    280     }
    281 
    282 
    283     /**
    284      * Returns the next thread in the queue.
    285      *
    286      * @return  a waiting thread, or <code>null</code> if there is none
    287      */
    288     public WaitingThread nextThread() {
    289         return this.waitingThreads.peek();
    290     }
    291 
    292 
    293     /**
    294      * Removes a waiting thread, if it is queued.
    295      *
    296      * @param wt        the waiting thread
    297      */
    298     public void removeThread(WaitingThread wt) {
    299         if (wt == null)
    300             return;
    301 
    302         this.waitingThreads.remove(wt);
    303     }
    304 
    305 
    306 } // class RouteSpecificPool
    307