mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/RouteSpecificPool.java

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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  */
    27 package ch.boye.httpclientandroidlib.impl.conn.tsccm;
    29 import java.io.IOException;
    30 import java.util.ListIterator;
    31 import java.util.Queue;
    32 import java.util.LinkedList;
    34 import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
    36 import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
    37 /* LogFactory removed by HttpClient for Android script. */
    38 import ch.boye.httpclientandroidlib.conn.OperatedClientConnection;
    39 import ch.boye.httpclientandroidlib.conn.params.ConnPerRoute;
    40 import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
    41 import ch.boye.httpclientandroidlib.util.LangUtils;
    44 /**
    45  * A connection sub-pool for a specific route, used by {@link ConnPoolByRoute}.
    46  * The methods in this class are unsynchronized. It is expected that the
    47  * containing pool takes care of synchronization.
    48  *
    49  * @since 4.0
    50  */
    51 @NotThreadSafe // e.g. numEntries, freeEntries,
    52 public class RouteSpecificPool {
    54     public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
    56     /** The route this pool is for. */
    57     protected final HttpRoute route; //Immutable
    59     @Deprecated
    60     protected final int maxEntries;
    62     /** Connections per route */
    63     protected final ConnPerRoute connPerRoute;
    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;
    72     /** The list of threads waiting for this pool. */
    73     protected final Queue<WaitingThread> waitingThreads;
    75     /** The number of created entries. */
    76     protected int numEntries;
    79     /**
    80      * @deprecated use {@link RouteSpecificPool#RouteSpecificPool(HttpRoute, ConnPerRoute)}
    81      */
    82     @Deprecated
    83     public RouteSpecificPool(HttpRoute route, int maxEntries) {
    84         this.route = route;
    85         this.maxEntries = maxEntries;
    86         this.connPerRoute = new ConnPerRoute() {
    87             public int getMaxForRoute(HttpRoute route) {
    88                 return RouteSpecificPool.this.maxEntries;
    89             }
    90         };
    91         this.freeEntries = new LinkedList<BasicPoolEntry>();
    92         this.waitingThreads = new LinkedList<WaitingThread>();
    93         this.numEntries = 0;
    94     }
    97     /**
    98      * Creates a new route-specific pool.
    99      *
   100      * @param route the route for which to pool
   101      * @param connPerRoute the connections per route configuration
   102      */
   103     public RouteSpecificPool(HttpRoute route, ConnPerRoute connPerRoute) {
   104         this.route = route;
   105         this.connPerRoute = connPerRoute;
   106         this.maxEntries = connPerRoute.getMaxForRoute(route);
   107         this.freeEntries = new LinkedList<BasicPoolEntry>();
   108         this.waitingThreads = new LinkedList<WaitingThread>();
   109         this.numEntries = 0;
   110     }
   113     /**
   114      * Obtains the route for which this pool is specific.
   115      *
   116      * @return  the route
   117      */
   118     public final HttpRoute getRoute() {
   119         return route;
   120     }
   123     /**
   124      * Obtains the maximum number of entries allowed for this pool.
   125      *
   126      * @return  the max entry number
   127      */
   128     public final int getMaxEntries() {
   129         return maxEntries;
   130     }
   133     /**
   134      * Indicates whether this pool is unused.
   135      * A pool is unused if there is neither an entry nor a waiting thread.
   136      * All entries count, not only the free but also the allocated ones.
   137      *
   138      * @return  <code>true</code> if this pool is unused,
   139      *          <code>false</code> otherwise
   140      */
   141     public boolean isUnused() {
   142         return (numEntries < 1) && waitingThreads.isEmpty();
   143     }
   146     /**
   147      * Return remaining capacity of this pool
   148      *
   149      * @return capacity
   150      */
   151     public int getCapacity() {
   152         return connPerRoute.getMaxForRoute(route) - numEntries;
   153     }
   156     /**
   157      * Obtains the number of entries.
   158      * This includes not only the free entries, but also those that
   159      * have been created and are currently issued to an application.
   160      *
   161      * @return  the number of entries for the route of this pool
   162      */
   163     public final int getEntryCount() {
   164         return numEntries;
   165     }
   168     /**
   169      * Obtains a free entry from this pool, if one is available.
   170      *
   171      * @return an available pool entry, or <code>null</code> if there is none
   172      */
   173     public BasicPoolEntry allocEntry(final Object state) {
   174         if (!freeEntries.isEmpty()) {
   175             ListIterator<BasicPoolEntry> it = freeEntries.listIterator(freeEntries.size());
   176             while (it.hasPrevious()) {
   177                 BasicPoolEntry entry = it.previous();
   178                 if (entry.getState() == null || LangUtils.equals(state, entry.getState())) {
   179                     it.remove();
   180                     return entry;
   181                 }
   182             }
   183         }
   184         if (getCapacity() == 0 && !freeEntries.isEmpty()) {
   185             BasicPoolEntry entry = freeEntries.remove();
   186             entry.shutdownEntry();
   187             OperatedClientConnection conn = entry.getConnection();
   188             try {
   189                 conn.close();
   190             } catch (IOException ex) {
   191                 log.debug("I/O error closing connection", ex);
   192             }
   193             return entry;
   194         }
   195         return null;
   196     }
   199     /**
   200      * Returns an allocated entry to this pool.
   201      *
   202      * @param entry     the entry obtained from {@link #allocEntry allocEntry}
   203      *                  or presented to {@link #createdEntry createdEntry}
   204      */
   205     public void freeEntry(BasicPoolEntry entry) {
   207         if (numEntries < 1) {
   208             throw new IllegalStateException
   209                 ("No entry created for this pool. " + route);
   210         }
   211         if (numEntries <= freeEntries.size()) {
   212             throw new IllegalStateException
   213                 ("No entry allocated from this pool. " + route);
   214         }
   215         freeEntries.add(entry);
   216     }
   219     /**
   220      * Indicates creation of an entry for this pool.
   221      * The entry will <i>not</i> be added to the list of free entries,
   222      * it is only recognized as belonging to this pool now. It can then
   223      * be passed to {@link #freeEntry freeEntry}.
   224      *
   225      * @param entry     the entry that was created for this pool
   226      */
   227     public void createdEntry(BasicPoolEntry entry) {
   229         if (!route.equals(entry.getPlannedRoute())) {
   230             throw new IllegalArgumentException
   231                 ("Entry not planned for this pool." +
   232                  "\npool: " + route +
   233                  "\nplan: " + entry.getPlannedRoute());
   234         }
   236         numEntries++;
   237     }
   240     /**
   241      * Deletes an entry from this pool.
   242      * Only entries that are currently free in this pool can be deleted.
   243      * Allocated entries can not be deleted.
   244      *
   245      * @param entry     the entry to delete from this pool
   246      *
   247      * @return  <code>true</code> if the entry was found and deleted, or
   248      *          <code>false</code> if the entry was not found
   249      */
   250     public boolean deleteEntry(BasicPoolEntry entry) {
   252         final boolean found = freeEntries.remove(entry);
   253         if (found)
   254             numEntries--;
   255         return found;
   256     }
   259     /**
   260      * Forgets about an entry from this pool.
   261      * This method is used to indicate that an entry
   262      * {@link #allocEntry allocated}
   263      * from this pool has been lost and will not be returned.
   264      */
   265     public void dropEntry() {
   266         if (numEntries < 1) {
   267             throw new IllegalStateException
   268                 ("There is no entry that could be dropped.");
   269         }
   270         numEntries--;
   271     }
   274     /**
   275      * Adds a waiting thread.
   276      * This pool makes no attempt to match waiting threads with pool entries.
   277      * It is the caller's responsibility to check that there is no entry
   278      * before adding a waiting thread.
   279      *
   280      * @param wt        the waiting thread
   281      */
   282     public void queueThread(WaitingThread wt) {
   283         if (wt == null) {
   284             throw new IllegalArgumentException
   285                 ("Waiting thread must not be null.");
   286         }
   287         this.waitingThreads.add(wt);
   288     }
   291     /**
   292      * Checks whether there is a waiting thread in this pool.
   293      *
   294      * @return  <code>true</code> if there is a waiting thread,
   295      *          <code>false</code> otherwise
   296      */
   297     public boolean hasThread() {
   298         return !this.waitingThreads.isEmpty();
   299     }
   302     /**
   303      * Returns the next thread in the queue.
   304      *
   305      * @return  a waiting thread, or <code>null</code> if there is none
   306      */
   307     public WaitingThread nextThread() {
   308         return this.waitingThreads.peek();
   309     }
   312     /**
   313      * Removes a waiting thread, if it is queued.
   314      *
   315      * @param wt        the waiting thread
   316      */
   317     public void removeThread(WaitingThread wt) {
   318         if (wt == null)
   319             return;
   321         this.waitingThreads.remove(wt);
   322     }
   325 } // class RouteSpecificPool

mercurial