blob: 3c50b4fbd9e7738030f7dc2061893ee279f282b4 [file] [log] [blame]
/*
* $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/conn/tsccm/RouteSpecificPool.java $
* $Revision: 677240 $
* $Date: 2008-07-16 04:25:47 -0700 (Wed, 16 Jul 2008) $
*
* ====================================================================
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.http.impl.conn.tsccm;
import java.io.IOException;
import java.util.ListIterator;
import java.util.Queue;
import java.util.LinkedList;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.conn.OperatedClientConnection;
import org.apache.http.conn.routing.HttpRoute;
import org.apache.http.util.LangUtils;
/**
* A connection sub-pool for a specific route, used by {@link ConnPoolByRoute}.
* The methods in this class are unsynchronized. It is expected that the
* containing pool takes care of synchronization.
*
* @deprecated Please use {@link java.net.URL#openConnection} instead.
* Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a>
* for further details.
*/
@Deprecated
public class RouteSpecificPool {
private final Log log = LogFactory.getLog(getClass());
/** The route this pool is for. */
protected final HttpRoute route;
/** the maximum number of entries allowed for this pool */
protected final int maxEntries;
/**
* The list of free entries.
* This list is managed LIFO, to increase idle times and
* allow for closing connections that are not really needed.
*/
protected final LinkedList<BasicPoolEntry> freeEntries;
/** The list of threads waiting for this pool. */
protected final Queue<WaitingThread> waitingThreads;
/** The number of created entries. */
protected int numEntries;
/**
* Creates a new route-specific pool.
*
* @param route the route for which to pool
* @param maxEntries the maximum number of entries allowed for this pool
*/
public RouteSpecificPool(HttpRoute route, int maxEntries) {
this.route = route;
this.maxEntries = maxEntries;
this.freeEntries = new LinkedList<BasicPoolEntry>();
this.waitingThreads = new LinkedList<WaitingThread>();
this.numEntries = 0;
}
/**
* Obtains the route for which this pool is specific.
*
* @return the route
*/
public final HttpRoute getRoute() {
return route;
}
/**
* Obtains the maximum number of entries allowed for this pool.
*
* @return the max entry number
*/
public final int getMaxEntries() {
return maxEntries;
}
/**
* Indicates whether this pool is unused.
* A pool is unused if there is neither an entry nor a waiting thread.
* All entries count, not only the free but also the allocated ones.
*
* @return <code>true</code> if this pool is unused,
* <code>false</code> otherwise
*/
public boolean isUnused() {
return (numEntries < 1) && waitingThreads.isEmpty();
}
/**
* Return remaining capacity of this pool
*
* @return capacity
*/
public int getCapacity() {
return maxEntries - numEntries;
}
/**
* Obtains the number of entries.
* This includes not only the free entries, but also those that
* have been created and are currently issued to an application.
*
* @return the number of entries for the route of this pool
*/
public final int getEntryCount() {
return numEntries;
}
/**
* Obtains a free entry from this pool, if one is available.
*
* @return an available pool entry, or <code>null</code> if there is none
*/
public BasicPoolEntry allocEntry(final Object state) {
if (!freeEntries.isEmpty()) {
ListIterator<BasicPoolEntry> it = freeEntries.listIterator(freeEntries.size());
while (it.hasPrevious()) {
BasicPoolEntry entry = it.previous();
if (LangUtils.equals(state, entry.getState())) {
it.remove();
return entry;
}
}
}
if (!freeEntries.isEmpty()) {
BasicPoolEntry entry = freeEntries.remove();
entry.setState(null);
OperatedClientConnection conn = entry.getConnection();
try {
conn.close();
} catch (IOException ex) {
log.debug("I/O error closing connection", ex);
}
return entry;
}
return null;
}
/**
* Returns an allocated entry to this pool.
*
* @param entry the entry obtained from {@link #allocEntry allocEntry}
* or presented to {@link #createdEntry createdEntry}
*/
public void freeEntry(BasicPoolEntry entry) {
if (numEntries < 1) {
throw new IllegalStateException
("No entry created for this pool. " + route);
}
if (numEntries <= freeEntries.size()) {
throw new IllegalStateException
("No entry allocated from this pool. " + route);
}
freeEntries.add(entry);
}
/**
* Indicates creation of an entry for this pool.
* The entry will <i>not</i> be added to the list of free entries,
* it is only recognized as belonging to this pool now. It can then
* be passed to {@link #freeEntry freeEntry}.
*
* @param entry the entry that was created for this pool
*/
public void createdEntry(BasicPoolEntry entry) {
if (!route.equals(entry.getPlannedRoute())) {
throw new IllegalArgumentException
("Entry not planned for this pool." +
"\npool: " + route +
"\nplan: " + entry.getPlannedRoute());
}
numEntries++;
}
/**
* Deletes an entry from this pool.
* Only entries that are currently free in this pool can be deleted.
* Allocated entries can not be deleted.
*
* @param entry the entry to delete from this pool
*
* @return <code>true</code> if the entry was found and deleted, or
* <code>false</code> if the entry was not found
*/
public boolean deleteEntry(BasicPoolEntry entry) {
final boolean found = freeEntries.remove(entry);
if (found)
numEntries--;
return found;
}
/**
* Forgets about an entry from this pool.
* This method is used to indicate that an entry
* {@link #allocEntry allocated}
* from this pool has been lost and will not be returned.
*/
public void dropEntry() {
if (numEntries < 1) {
throw new IllegalStateException
("There is no entry that could be dropped.");
}
numEntries--;
}
/**
* Adds a waiting thread.
* This pool makes no attempt to match waiting threads with pool entries.
* It is the caller's responsibility to check that there is no entry
* before adding a waiting thread.
*
* @param wt the waiting thread
*/
public void queueThread(WaitingThread wt) {
if (wt == null) {
throw new IllegalArgumentException
("Waiting thread must not be null.");
}
this.waitingThreads.add(wt);
}
/**
* Checks whether there is a waiting thread in this pool.
*
* @return <code>true</code> if there is a waiting thread,
* <code>false</code> otherwise
*/
public boolean hasThread() {
return !this.waitingThreads.isEmpty();
}
/**
* Returns the next thread in the queue.
*
* @return a waiting thread, or <code>null</code> if there is none
*/
public WaitingThread nextThread() {
return this.waitingThreads.peek();
}
/**
* Removes a waiting thread, if it is queued.
*
* @param wt the waiting thread
*/
public void removeThread(WaitingThread wt) {
if (wt == null)
return;
this.waitingThreads.remove(wt);
}
} // class RouteSpecificPool