mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-09 09:18:42 +09:00
pt 1 in reviving the android build (copied from pm 28a1, wish me luck)
This commit is contained in:
parent
efa9662725
commit
d7788a6d6d
4249 changed files with 468189 additions and 0 deletions
234
mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/AbstractConnPool.java
vendored
Normal file
234
mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/AbstractConnPool.java
vendored
Normal file
|
|
@ -0,0 +1,234 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* 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 ch.boye.httpclientandroidlib.impl.conn.tsccm;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
|
||||
/* LogFactory removed by HttpClient for Android script. */
|
||||
import ch.boye.httpclientandroidlib.annotation.GuardedBy;
|
||||
import ch.boye.httpclientandroidlib.conn.ConnectionPoolTimeoutException;
|
||||
import ch.boye.httpclientandroidlib.conn.OperatedClientConnection;
|
||||
import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
|
||||
import ch.boye.httpclientandroidlib.impl.conn.IdleConnectionHandler;
|
||||
import ch.boye.httpclientandroidlib.util.Args;
|
||||
|
||||
/**
|
||||
* An abstract connection pool.
|
||||
* It is used by the {@link ThreadSafeClientConnManager}.
|
||||
* The abstract pool includes a {@link #poolLock}, which is used to
|
||||
* synchronize access to the internal pool datastructures.
|
||||
* Don't use <code>synchronized</code> for that purpose!
|
||||
*
|
||||
* @since 4.0
|
||||
*
|
||||
* @deprecated (4.2) use {@link ch.boye.httpclientandroidlib.pool.AbstractConnPool}
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract class AbstractConnPool {
|
||||
|
||||
public HttpClientAndroidLog log;
|
||||
|
||||
/**
|
||||
* The global lock for this pool.
|
||||
*/
|
||||
protected final Lock poolLock;
|
||||
|
||||
/** References to issued connections */
|
||||
@GuardedBy("poolLock")
|
||||
protected Set<BasicPoolEntry> leasedConnections;
|
||||
|
||||
/** The current total number of connections. */
|
||||
@GuardedBy("poolLock")
|
||||
protected int numConnections;
|
||||
|
||||
/** Indicates whether this pool is shut down. */
|
||||
protected volatile boolean isShutDown;
|
||||
|
||||
protected Set<BasicPoolEntryRef> issuedConnections;
|
||||
|
||||
protected ReferenceQueue<Object> refQueue;
|
||||
|
||||
protected IdleConnectionHandler idleConnHandler;
|
||||
|
||||
/**
|
||||
* Creates a new connection pool.
|
||||
*/
|
||||
protected AbstractConnPool() {
|
||||
super();
|
||||
this.log = new HttpClientAndroidLog(getClass());
|
||||
this.leasedConnections = new HashSet<BasicPoolEntry>();
|
||||
this.idleConnHandler = new IdleConnectionHandler();
|
||||
this.poolLock = new ReentrantLock();
|
||||
}
|
||||
|
||||
public void enableConnectionGC()
|
||||
throws IllegalStateException {
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a pool entry with a connection within the given timeout.
|
||||
*
|
||||
* @param route the route for which to get the connection
|
||||
* @param timeout the timeout, 0 or negative for no timeout
|
||||
* @param tunit the unit for the <code>timeout</code>,
|
||||
* may be <code>null</code> only if there is no timeout
|
||||
*
|
||||
* @return pool entry holding a connection for the route
|
||||
*
|
||||
* @throws ConnectionPoolTimeoutException
|
||||
* if the timeout expired
|
||||
* @throws InterruptedException
|
||||
* if the calling thread was interrupted
|
||||
*/
|
||||
public final
|
||||
BasicPoolEntry getEntry(
|
||||
final HttpRoute route,
|
||||
final Object state,
|
||||
final long timeout,
|
||||
final TimeUnit tunit)
|
||||
throws ConnectionPoolTimeoutException, InterruptedException {
|
||||
return requestPoolEntry(route, state).getPoolEntry(timeout, tunit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new {@link PoolEntryRequest}, from which a {@link BasicPoolEntry}
|
||||
* can be obtained, or the request can be aborted.
|
||||
*/
|
||||
public abstract PoolEntryRequest requestPoolEntry(HttpRoute route, Object state);
|
||||
|
||||
|
||||
/**
|
||||
* Returns an entry into the pool.
|
||||
* The connection of the entry is expected to be in a suitable state,
|
||||
* either open and re-usable, or closed. The pool will not make any
|
||||
* attempt to determine whether it can be re-used or not.
|
||||
*
|
||||
* @param entry the entry for the connection to release
|
||||
* @param reusable <code>true</code> if the entry is deemed
|
||||
* reusable, <code>false</code> otherwise.
|
||||
* @param validDuration The duration that the entry should remain free and reusable.
|
||||
* @param timeUnit The unit of time the duration is measured in.
|
||||
*/
|
||||
public abstract void freeEntry(BasicPoolEntry entry, boolean reusable, long validDuration, TimeUnit timeUnit)
|
||||
;
|
||||
|
||||
public void handleReference(final Reference<?> ref) {
|
||||
}
|
||||
|
||||
protected abstract void handleLostEntry(HttpRoute route);
|
||||
|
||||
/**
|
||||
* Closes idle connections.
|
||||
*
|
||||
* @param idletime the time the connections should have been idle
|
||||
* in order to be closed now
|
||||
* @param tunit the unit for the <code>idletime</code>
|
||||
*/
|
||||
public void closeIdleConnections(final long idletime, final TimeUnit tunit) {
|
||||
|
||||
// idletime can be 0 or negative, no problem there
|
||||
Args.notNull(tunit, "Time unit");
|
||||
|
||||
poolLock.lock();
|
||||
try {
|
||||
idleConnHandler.closeIdleConnections(tunit.toMillis(idletime));
|
||||
} finally {
|
||||
poolLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void closeExpiredConnections() {
|
||||
poolLock.lock();
|
||||
try {
|
||||
idleConnHandler.closeExpiredConnections();
|
||||
} finally {
|
||||
poolLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deletes all entries for closed connections.
|
||||
*/
|
||||
public abstract void deleteClosedConnections();
|
||||
|
||||
/**
|
||||
* Shuts down this pool and all associated resources.
|
||||
* Overriding methods MUST call the implementation here!
|
||||
*/
|
||||
public void shutdown() {
|
||||
|
||||
poolLock.lock();
|
||||
try {
|
||||
|
||||
if (isShutDown) {
|
||||
return;
|
||||
}
|
||||
|
||||
// close all connections that are issued to an application
|
||||
final Iterator<BasicPoolEntry> iter = leasedConnections.iterator();
|
||||
while (iter.hasNext()) {
|
||||
final BasicPoolEntry entry = iter.next();
|
||||
iter.remove();
|
||||
closeConnection(entry.getConnection());
|
||||
}
|
||||
idleConnHandler.removeAll();
|
||||
|
||||
isShutDown = true;
|
||||
|
||||
} finally {
|
||||
poolLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Closes a connection from this pool.
|
||||
*
|
||||
* @param conn the connection to close, or <code>null</code>
|
||||
*/
|
||||
protected void closeConnection(final OperatedClientConnection conn) {
|
||||
if (conn != null) {
|
||||
try {
|
||||
conn.close();
|
||||
} catch (final IOException ex) {
|
||||
log.debug("I/O error closing connection", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // class AbstractConnPool
|
||||
|
||||
163
mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/BasicPoolEntry.java
vendored
Normal file
163
mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/BasicPoolEntry.java
vendored
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* 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 ch.boye.httpclientandroidlib.impl.conn.tsccm;
|
||||
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import ch.boye.httpclientandroidlib.conn.ClientConnectionOperator;
|
||||
import ch.boye.httpclientandroidlib.conn.OperatedClientConnection;
|
||||
import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
|
||||
import ch.boye.httpclientandroidlib.impl.conn.AbstractPoolEntry;
|
||||
import ch.boye.httpclientandroidlib.util.Args;
|
||||
|
||||
/**
|
||||
* Basic implementation of a connection pool entry.
|
||||
*
|
||||
* @since 4.0
|
||||
*
|
||||
* @deprecated (4.2) use {@link ch.boye.httpclientandroidlib.pool.PoolEntry}
|
||||
*/
|
||||
@Deprecated
|
||||
public class BasicPoolEntry extends AbstractPoolEntry {
|
||||
|
||||
private final long created;
|
||||
|
||||
private long updated;
|
||||
private final long validUntil;
|
||||
private long expiry;
|
||||
|
||||
public BasicPoolEntry(final ClientConnectionOperator op,
|
||||
final HttpRoute route,
|
||||
final ReferenceQueue<Object> queue) {
|
||||
super(op, route);
|
||||
Args.notNull(route, "HTTP route");
|
||||
this.created = System.currentTimeMillis();
|
||||
this.validUntil = Long.MAX_VALUE;
|
||||
this.expiry = this.validUntil;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new pool entry.
|
||||
*
|
||||
* @param op the connection operator
|
||||
* @param route the planned route for the connection
|
||||
*/
|
||||
public BasicPoolEntry(final ClientConnectionOperator op,
|
||||
final HttpRoute route) {
|
||||
this(op, route, -1, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new pool entry with a specified maximum lifetime.
|
||||
*
|
||||
* @param op the connection operator
|
||||
* @param route the planned route for the connection
|
||||
* @param connTTL maximum lifetime of this entry, <=0 implies "infinity"
|
||||
* @param timeunit TimeUnit of connTTL
|
||||
*
|
||||
* @since 4.1
|
||||
*/
|
||||
public BasicPoolEntry(final ClientConnectionOperator op,
|
||||
final HttpRoute route, final long connTTL, final TimeUnit timeunit) {
|
||||
super(op, route);
|
||||
Args.notNull(route, "HTTP route");
|
||||
this.created = System.currentTimeMillis();
|
||||
if (connTTL > 0) {
|
||||
this.validUntil = this.created + timeunit.toMillis(connTTL);
|
||||
} else {
|
||||
this.validUntil = Long.MAX_VALUE;
|
||||
}
|
||||
this.expiry = this.validUntil;
|
||||
}
|
||||
|
||||
protected final OperatedClientConnection getConnection() {
|
||||
return super.connection;
|
||||
}
|
||||
|
||||
protected final HttpRoute getPlannedRoute() {
|
||||
return super.route;
|
||||
}
|
||||
|
||||
protected final BasicPoolEntryRef getWeakRef() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutdownEntry() {
|
||||
super.shutdownEntry();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.1
|
||||
*/
|
||||
public long getCreated() {
|
||||
return this.created;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.1
|
||||
*/
|
||||
public long getUpdated() {
|
||||
return this.updated;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.1
|
||||
*/
|
||||
public long getExpiry() {
|
||||
return this.expiry;
|
||||
}
|
||||
|
||||
public long getValidUntil() {
|
||||
return this.validUntil;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.1
|
||||
*/
|
||||
public void updateExpiry(final long time, final TimeUnit timeunit) {
|
||||
this.updated = System.currentTimeMillis();
|
||||
final long newExpiry;
|
||||
if (time > 0) {
|
||||
newExpiry = this.updated + timeunit.toMillis(time);
|
||||
} else {
|
||||
newExpiry = Long.MAX_VALUE;
|
||||
}
|
||||
this.expiry = Math.min(validUntil, newExpiry);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.1
|
||||
*/
|
||||
public boolean isExpired(final long now) {
|
||||
return now >= this.expiry;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
76
mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/BasicPoolEntryRef.java
vendored
Normal file
76
mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/BasicPoolEntryRef.java
vendored
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* 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 ch.boye.httpclientandroidlib.impl.conn.tsccm;
|
||||
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
|
||||
import ch.boye.httpclientandroidlib.util.Args;
|
||||
|
||||
/**
|
||||
* A weak reference to a {@link BasicPoolEntry BasicPoolEntry}.
|
||||
* This reference explicitly keeps the planned route, so the connection
|
||||
* can be reclaimed if it is lost to garbage collection.
|
||||
*
|
||||
* @since 4.0
|
||||
*
|
||||
* @deprecated (4.2) do not use
|
||||
*/
|
||||
@Deprecated
|
||||
public class BasicPoolEntryRef extends WeakReference<BasicPoolEntry> {
|
||||
|
||||
/** The planned route of the entry. */
|
||||
private final HttpRoute route; // HttpRoute is @Immutable
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new reference to a pool entry.
|
||||
*
|
||||
* @param entry the pool entry, must not be <code>null</code>
|
||||
* @param queue the reference queue, or <code>null</code>
|
||||
*/
|
||||
public BasicPoolEntryRef(final BasicPoolEntry entry,
|
||||
final ReferenceQueue<Object> queue) {
|
||||
super(entry, queue);
|
||||
Args.notNull(entry, "Pool entry");
|
||||
route = entry.getPlannedRoute();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Obtain the planned route for the referenced entry.
|
||||
* The planned route is still available, even if the entry is gone.
|
||||
*
|
||||
* @return the planned route
|
||||
*/
|
||||
public final HttpRoute getRoute() {
|
||||
return this.route;
|
||||
}
|
||||
|
||||
} // class BasicPoolEntryRef
|
||||
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* 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 ch.boye.httpclientandroidlib.impl.conn.tsccm;
|
||||
|
||||
import ch.boye.httpclientandroidlib.conn.ClientConnectionManager;
|
||||
import ch.boye.httpclientandroidlib.impl.conn.AbstractPoolEntry;
|
||||
import ch.boye.httpclientandroidlib.impl.conn.AbstractPooledConnAdapter;
|
||||
|
||||
/**
|
||||
* A connection wrapper and callback handler.
|
||||
* All connections given out by the manager are wrappers which
|
||||
* can be {@link #detach detach}ed to prevent further use on release.
|
||||
*
|
||||
* @since 4.0
|
||||
*
|
||||
* @deprecated (4.2) do not use
|
||||
*/
|
||||
@Deprecated
|
||||
public class BasicPooledConnAdapter extends AbstractPooledConnAdapter {
|
||||
|
||||
/**
|
||||
* Creates a new adapter.
|
||||
*
|
||||
* @param tsccm the connection manager
|
||||
* @param entry the pool entry for the connection being wrapped
|
||||
*/
|
||||
protected BasicPooledConnAdapter(final ThreadSafeClientConnManager tsccm,
|
||||
final AbstractPoolEntry entry) {
|
||||
super(tsccm, entry);
|
||||
markReusable();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ClientConnectionManager getManager() {
|
||||
// override needed only to make method visible in this package
|
||||
return super.getManager();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractPoolEntry getPoolEntry() {
|
||||
// override needed only to make method visible in this package
|
||||
return super.getPoolEntry();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void detach() {
|
||||
// override needed only to make method visible in this package
|
||||
super.detach();
|
||||
}
|
||||
|
||||
}
|
||||
829
mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/ConnPoolByRoute.java
vendored
Normal file
829
mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/ConnPoolByRoute.java
vendored
Normal file
|
|
@ -0,0 +1,829 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* 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 ch.boye.httpclientandroidlib.impl.conn.tsccm;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Map;
|
||||
import java.util.Queue;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.Condition;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
|
||||
import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
|
||||
/* LogFactory removed by HttpClient for Android script. */
|
||||
import ch.boye.httpclientandroidlib.conn.ClientConnectionOperator;
|
||||
import ch.boye.httpclientandroidlib.conn.ConnectionPoolTimeoutException;
|
||||
import ch.boye.httpclientandroidlib.conn.OperatedClientConnection;
|
||||
import ch.boye.httpclientandroidlib.conn.params.ConnManagerParams;
|
||||
import ch.boye.httpclientandroidlib.conn.params.ConnPerRoute;
|
||||
import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
|
||||
import ch.boye.httpclientandroidlib.params.HttpParams;
|
||||
import ch.boye.httpclientandroidlib.util.Args;
|
||||
import ch.boye.httpclientandroidlib.util.Asserts;
|
||||
|
||||
/**
|
||||
* A connection pool that maintains connections by route.
|
||||
* This class is derived from <code>MultiThreadedHttpConnectionManager</code>
|
||||
* in HttpClient 3.x, see there for original authors. It implements the same
|
||||
* algorithm for connection re-use and connection-per-host enforcement:
|
||||
* <ul>
|
||||
* <li>connections are re-used only for the exact same route</li>
|
||||
* <li>connection limits are enforced per route rather than per host</li>
|
||||
* </ul>
|
||||
* Note that access to the pool data structures is synchronized via the
|
||||
* {@link AbstractConnPool#poolLock poolLock} in the base class,
|
||||
* not via <code>synchronized</code> methods.
|
||||
*
|
||||
* @since 4.0
|
||||
*
|
||||
* @deprecated (4.2) use {@link ch.boye.httpclientandroidlib.pool.AbstractConnPool}
|
||||
*/
|
||||
@Deprecated
|
||||
public class ConnPoolByRoute extends AbstractConnPool {
|
||||
|
||||
public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
|
||||
|
||||
private final Lock poolLock;
|
||||
|
||||
/** Connection operator for this pool */
|
||||
protected final ClientConnectionOperator operator;
|
||||
|
||||
/** Connections per route lookup */
|
||||
protected final ConnPerRoute connPerRoute;
|
||||
|
||||
/** References to issued connections */
|
||||
protected final Set<BasicPoolEntry> leasedConnections;
|
||||
|
||||
/** The list of free connections */
|
||||
protected final Queue<BasicPoolEntry> freeConnections;
|
||||
|
||||
/** The list of WaitingThreads waiting for a connection */
|
||||
protected final Queue<WaitingThread> waitingThreads;
|
||||
|
||||
/** Map of route-specific pools */
|
||||
protected final Map<HttpRoute, RouteSpecificPool> routeToPool;
|
||||
|
||||
private final long connTTL;
|
||||
|
||||
private final TimeUnit connTTLTimeUnit;
|
||||
|
||||
protected volatile boolean shutdown;
|
||||
|
||||
protected volatile int maxTotalConnections;
|
||||
|
||||
protected volatile int numConnections;
|
||||
|
||||
/**
|
||||
* Creates a new connection pool, managed by route.
|
||||
*
|
||||
* @since 4.1
|
||||
*/
|
||||
public ConnPoolByRoute(
|
||||
final ClientConnectionOperator operator,
|
||||
final ConnPerRoute connPerRoute,
|
||||
final int maxTotalConnections) {
|
||||
this(operator, connPerRoute, maxTotalConnections, -1, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.1
|
||||
*/
|
||||
public ConnPoolByRoute(
|
||||
final ClientConnectionOperator operator,
|
||||
final ConnPerRoute connPerRoute,
|
||||
final int maxTotalConnections,
|
||||
final long connTTL,
|
||||
final TimeUnit connTTLTimeUnit) {
|
||||
super();
|
||||
Args.notNull(operator, "Connection operator");
|
||||
Args.notNull(connPerRoute, "Connections per route");
|
||||
this.poolLock = super.poolLock;
|
||||
this.leasedConnections = super.leasedConnections;
|
||||
this.operator = operator;
|
||||
this.connPerRoute = connPerRoute;
|
||||
this.maxTotalConnections = maxTotalConnections;
|
||||
this.freeConnections = createFreeConnQueue();
|
||||
this.waitingThreads = createWaitingThreadQueue();
|
||||
this.routeToPool = createRouteToPoolMap();
|
||||
this.connTTL = connTTL;
|
||||
this.connTTLTimeUnit = connTTLTimeUnit;
|
||||
}
|
||||
|
||||
protected Lock getLock() {
|
||||
return this.poolLock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new connection pool, managed by route.
|
||||
*
|
||||
* @deprecated (4.1) use {@link ConnPoolByRoute#ConnPoolByRoute(ClientConnectionOperator, ConnPerRoute, int)}
|
||||
*/
|
||||
@Deprecated
|
||||
public ConnPoolByRoute(final ClientConnectionOperator operator, final HttpParams params) {
|
||||
this(operator,
|
||||
ConnManagerParams.getMaxConnectionsPerRoute(params),
|
||||
ConnManagerParams.getMaxTotalConnections(params));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the queue for {@link #freeConnections}.
|
||||
* Called once by the constructor.
|
||||
*
|
||||
* @return a queue
|
||||
*/
|
||||
protected Queue<BasicPoolEntry> createFreeConnQueue() {
|
||||
return new LinkedList<BasicPoolEntry>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the queue for {@link #waitingThreads}.
|
||||
* Called once by the constructor.
|
||||
*
|
||||
* @return a queue
|
||||
*/
|
||||
protected Queue<WaitingThread> createWaitingThreadQueue() {
|
||||
return new LinkedList<WaitingThread>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the map for {@link #routeToPool}.
|
||||
* Called once by the constructor.
|
||||
*
|
||||
* @return a map
|
||||
*/
|
||||
protected Map<HttpRoute, RouteSpecificPool> createRouteToPoolMap() {
|
||||
return new HashMap<HttpRoute, RouteSpecificPool>();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new route-specific pool.
|
||||
* Called by {@link #getRoutePool} when necessary.
|
||||
*
|
||||
* @param route the route
|
||||
*
|
||||
* @return the new pool
|
||||
*/
|
||||
protected RouteSpecificPool newRouteSpecificPool(final HttpRoute route) {
|
||||
return new RouteSpecificPool(route, this.connPerRoute);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new waiting thread.
|
||||
* Called by {@link #getRoutePool} when necessary.
|
||||
*
|
||||
* @param cond the condition to wait for
|
||||
* @param rospl the route specific pool, or <code>null</code>
|
||||
*
|
||||
* @return a waiting thread representation
|
||||
*/
|
||||
protected WaitingThread newWaitingThread(final Condition cond,
|
||||
final RouteSpecificPool rospl) {
|
||||
return new WaitingThread(cond, rospl);
|
||||
}
|
||||
|
||||
private void closeConnection(final BasicPoolEntry entry) {
|
||||
final OperatedClientConnection conn = entry.getConnection();
|
||||
if (conn != null) {
|
||||
try {
|
||||
conn.close();
|
||||
} catch (final IOException ex) {
|
||||
log.debug("I/O error closing connection", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a route-specific pool of available connections.
|
||||
*
|
||||
* @param route the route
|
||||
* @param create whether to create the pool if it doesn't exist
|
||||
*
|
||||
* @return the pool for the argument route,
|
||||
* never <code>null</code> if <code>create</code> is <code>true</code>
|
||||
*/
|
||||
protected RouteSpecificPool getRoutePool(final HttpRoute route,
|
||||
final boolean create) {
|
||||
RouteSpecificPool rospl = null;
|
||||
poolLock.lock();
|
||||
try {
|
||||
|
||||
rospl = routeToPool.get(route);
|
||||
if ((rospl == null) && create) {
|
||||
// no pool for this route yet (or anymore)
|
||||
rospl = newRouteSpecificPool(route);
|
||||
routeToPool.put(route, rospl);
|
||||
}
|
||||
|
||||
} finally {
|
||||
poolLock.unlock();
|
||||
}
|
||||
|
||||
return rospl;
|
||||
}
|
||||
|
||||
public int getConnectionsInPool(final HttpRoute route) {
|
||||
poolLock.lock();
|
||||
try {
|
||||
// don't allow a pool to be created here!
|
||||
final RouteSpecificPool rospl = getRoutePool(route, false);
|
||||
return (rospl != null) ? rospl.getEntryCount() : 0;
|
||||
|
||||
} finally {
|
||||
poolLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public int getConnectionsInPool() {
|
||||
poolLock.lock();
|
||||
try {
|
||||
return numConnections;
|
||||
} finally {
|
||||
poolLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PoolEntryRequest requestPoolEntry(
|
||||
final HttpRoute route,
|
||||
final Object state) {
|
||||
|
||||
final WaitingThreadAborter aborter = new WaitingThreadAborter();
|
||||
|
||||
return new PoolEntryRequest() {
|
||||
|
||||
public void abortRequest() {
|
||||
poolLock.lock();
|
||||
try {
|
||||
aborter.abort();
|
||||
} finally {
|
||||
poolLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public BasicPoolEntry getPoolEntry(
|
||||
final long timeout,
|
||||
final TimeUnit tunit)
|
||||
throws InterruptedException, ConnectionPoolTimeoutException {
|
||||
return getEntryBlocking(route, state, timeout, tunit, aborter);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a pool entry with a connection within the given timeout.
|
||||
* If a {@link WaitingThread} is used to block, {@link WaitingThreadAborter#setWaitingThread(WaitingThread)}
|
||||
* must be called before blocking, to allow the thread to be interrupted.
|
||||
*
|
||||
* @param route the route for which to get the connection
|
||||
* @param timeout the timeout, 0 or negative for no timeout
|
||||
* @param tunit the unit for the <code>timeout</code>,
|
||||
* may be <code>null</code> only if there is no timeout
|
||||
* @param aborter an object which can abort a {@link WaitingThread}.
|
||||
*
|
||||
* @return pool entry holding a connection for the route
|
||||
*
|
||||
* @throws ConnectionPoolTimeoutException
|
||||
* if the timeout expired
|
||||
* @throws InterruptedException
|
||||
* if the calling thread was interrupted
|
||||
*/
|
||||
protected BasicPoolEntry getEntryBlocking(
|
||||
final HttpRoute route, final Object state,
|
||||
final long timeout, final TimeUnit tunit,
|
||||
final WaitingThreadAborter aborter)
|
||||
throws ConnectionPoolTimeoutException, InterruptedException {
|
||||
|
||||
Date deadline = null;
|
||||
if (timeout > 0) {
|
||||
deadline = new Date
|
||||
(System.currentTimeMillis() + tunit.toMillis(timeout));
|
||||
}
|
||||
|
||||
BasicPoolEntry entry = null;
|
||||
poolLock.lock();
|
||||
try {
|
||||
|
||||
RouteSpecificPool rospl = getRoutePool(route, true);
|
||||
WaitingThread waitingThread = null;
|
||||
|
||||
while (entry == null) {
|
||||
Asserts.check(!shutdown, "Connection pool shut down");
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("[" + route + "] total kept alive: " + freeConnections.size() +
|
||||
", total issued: " + leasedConnections.size() +
|
||||
", total allocated: " + numConnections + " out of " + maxTotalConnections);
|
||||
}
|
||||
|
||||
// the cases to check for:
|
||||
// - have a free connection for that route
|
||||
// - allowed to create a free connection for that route
|
||||
// - can delete and replace a free connection for another route
|
||||
// - need to wait for one of the things above to come true
|
||||
|
||||
entry = getFreeEntry(rospl, state);
|
||||
if (entry != null) {
|
||||
break;
|
||||
}
|
||||
|
||||
final boolean hasCapacity = rospl.getCapacity() > 0;
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Available capacity: " + rospl.getCapacity()
|
||||
+ " out of " + rospl.getMaxEntries()
|
||||
+ " [" + route + "][" + state + "]");
|
||||
}
|
||||
|
||||
if (hasCapacity && numConnections < maxTotalConnections) {
|
||||
|
||||
entry = createEntry(rospl, operator);
|
||||
|
||||
} else if (hasCapacity && !freeConnections.isEmpty()) {
|
||||
|
||||
deleteLeastUsedEntry();
|
||||
// if least used entry's route was the same as rospl,
|
||||
// rospl is now out of date : we preemptively refresh
|
||||
rospl = getRoutePool(route, true);
|
||||
entry = createEntry(rospl, operator);
|
||||
|
||||
} else {
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Need to wait for connection" +
|
||||
" [" + route + "][" + state + "]");
|
||||
}
|
||||
|
||||
if (waitingThread == null) {
|
||||
waitingThread =
|
||||
newWaitingThread(poolLock.newCondition(), rospl);
|
||||
aborter.setWaitingThread(waitingThread);
|
||||
}
|
||||
|
||||
boolean success = false;
|
||||
try {
|
||||
rospl.queueThread(waitingThread);
|
||||
waitingThreads.add(waitingThread);
|
||||
success = waitingThread.await(deadline);
|
||||
|
||||
} finally {
|
||||
// In case of 'success', we were woken up by the
|
||||
// connection pool and should now have a connection
|
||||
// waiting for us, or else we're shutting down.
|
||||
// Just continue in the loop, both cases are checked.
|
||||
rospl.removeThread(waitingThread);
|
||||
waitingThreads.remove(waitingThread);
|
||||
}
|
||||
|
||||
// check for spurious wakeup vs. timeout
|
||||
if (!success && (deadline != null) &&
|
||||
(deadline.getTime() <= System.currentTimeMillis())) {
|
||||
throw new ConnectionPoolTimeoutException
|
||||
("Timeout waiting for connection from pool");
|
||||
}
|
||||
}
|
||||
} // while no entry
|
||||
|
||||
} finally {
|
||||
poolLock.unlock();
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void freeEntry(final BasicPoolEntry entry, final boolean reusable, final long validDuration, final TimeUnit timeUnit) {
|
||||
|
||||
final HttpRoute route = entry.getPlannedRoute();
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Releasing connection" +
|
||||
" [" + route + "][" + entry.getState() + "]");
|
||||
}
|
||||
|
||||
poolLock.lock();
|
||||
try {
|
||||
if (shutdown) {
|
||||
// the pool is shut down, release the
|
||||
// connection's resources and get out of here
|
||||
closeConnection(entry);
|
||||
return;
|
||||
}
|
||||
|
||||
// no longer issued, we keep a hard reference now
|
||||
leasedConnections.remove(entry);
|
||||
|
||||
final RouteSpecificPool rospl = getRoutePool(route, true);
|
||||
|
||||
if (reusable && rospl.getCapacity() >= 0) {
|
||||
if (log.isDebugEnabled()) {
|
||||
final String s;
|
||||
if (validDuration > 0) {
|
||||
s = "for " + validDuration + " " + timeUnit;
|
||||
} else {
|
||||
s = "indefinitely";
|
||||
}
|
||||
log.debug("Pooling connection" +
|
||||
" [" + route + "][" + entry.getState() + "]; keep alive " + s);
|
||||
}
|
||||
rospl.freeEntry(entry);
|
||||
entry.updateExpiry(validDuration, timeUnit);
|
||||
freeConnections.add(entry);
|
||||
} else {
|
||||
closeConnection(entry);
|
||||
rospl.dropEntry();
|
||||
numConnections--;
|
||||
}
|
||||
|
||||
notifyWaitingThread(rospl);
|
||||
|
||||
} finally {
|
||||
poolLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If available, get a free pool entry for a route.
|
||||
*
|
||||
* @param rospl the route-specific pool from which to get an entry
|
||||
*
|
||||
* @return an available pool entry for the given route, or
|
||||
* <code>null</code> if none is available
|
||||
*/
|
||||
protected BasicPoolEntry getFreeEntry(final RouteSpecificPool rospl, final Object state) {
|
||||
|
||||
BasicPoolEntry entry = null;
|
||||
poolLock.lock();
|
||||
try {
|
||||
boolean done = false;
|
||||
while(!done) {
|
||||
|
||||
entry = rospl.allocEntry(state);
|
||||
|
||||
if (entry != null) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Getting free connection"
|
||||
+ " [" + rospl.getRoute() + "][" + state + "]");
|
||||
|
||||
}
|
||||
freeConnections.remove(entry);
|
||||
if (entry.isExpired(System.currentTimeMillis())) {
|
||||
// If the free entry isn't valid anymore, get rid of it
|
||||
// and loop to find another one that might be valid.
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Closing expired free connection"
|
||||
+ " [" + rospl.getRoute() + "][" + state + "]");
|
||||
}
|
||||
closeConnection(entry);
|
||||
// We use dropEntry instead of deleteEntry because the entry
|
||||
// is no longer "free" (we just allocated it), and deleteEntry
|
||||
// can only be used to delete free entries.
|
||||
rospl.dropEntry();
|
||||
numConnections--;
|
||||
} else {
|
||||
leasedConnections.add(entry);
|
||||
done = true;
|
||||
}
|
||||
|
||||
} else {
|
||||
done = true;
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("No free connections"
|
||||
+ " [" + rospl.getRoute() + "][" + state + "]");
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
poolLock.unlock();
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new pool entry.
|
||||
* This method assumes that the new connection will be handed
|
||||
* out immediately.
|
||||
*
|
||||
* @param rospl the route-specific pool for which to create the entry
|
||||
* @param op the operator for creating a connection
|
||||
*
|
||||
* @return the new pool entry for a new connection
|
||||
*/
|
||||
protected BasicPoolEntry createEntry(final RouteSpecificPool rospl,
|
||||
final ClientConnectionOperator op) {
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Creating new connection [" + rospl.getRoute() + "]");
|
||||
}
|
||||
|
||||
// the entry will create the connection when needed
|
||||
final BasicPoolEntry entry = new BasicPoolEntry(op, rospl.getRoute(), connTTL, connTTLTimeUnit);
|
||||
|
||||
poolLock.lock();
|
||||
try {
|
||||
rospl.createdEntry(entry);
|
||||
numConnections++;
|
||||
leasedConnections.add(entry);
|
||||
} finally {
|
||||
poolLock.unlock();
|
||||
}
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deletes a given pool entry.
|
||||
* This closes the pooled connection and removes all references,
|
||||
* so that it can be GCed.
|
||||
*
|
||||
* <p><b>Note:</b> Does not remove the entry from the freeConnections list.
|
||||
* It is assumed that the caller has already handled this step.</p>
|
||||
* <!-- @@@ is that a good idea? or rather fix it? -->
|
||||
*
|
||||
* @param entry the pool entry for the connection to delete
|
||||
*/
|
||||
protected void deleteEntry(final BasicPoolEntry entry) {
|
||||
|
||||
final HttpRoute route = entry.getPlannedRoute();
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Deleting connection"
|
||||
+ " [" + route + "][" + entry.getState() + "]");
|
||||
}
|
||||
|
||||
poolLock.lock();
|
||||
try {
|
||||
|
||||
closeConnection(entry);
|
||||
|
||||
final RouteSpecificPool rospl = getRoutePool(route, true);
|
||||
rospl.deleteEntry(entry);
|
||||
numConnections--;
|
||||
if (rospl.isUnused()) {
|
||||
routeToPool.remove(route);
|
||||
}
|
||||
|
||||
} finally {
|
||||
poolLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Delete an old, free pool entry to make room for a new one.
|
||||
* Used to replace pool entries with ones for a different route.
|
||||
*/
|
||||
protected void deleteLeastUsedEntry() {
|
||||
poolLock.lock();
|
||||
try {
|
||||
|
||||
final BasicPoolEntry entry = freeConnections.remove();
|
||||
|
||||
if (entry != null) {
|
||||
deleteEntry(entry);
|
||||
} else if (log.isDebugEnabled()) {
|
||||
log.debug("No free connection to delete");
|
||||
}
|
||||
|
||||
} finally {
|
||||
poolLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleLostEntry(final HttpRoute route) {
|
||||
|
||||
poolLock.lock();
|
||||
try {
|
||||
|
||||
final RouteSpecificPool rospl = getRoutePool(route, true);
|
||||
rospl.dropEntry();
|
||||
if (rospl.isUnused()) {
|
||||
routeToPool.remove(route);
|
||||
}
|
||||
|
||||
numConnections--;
|
||||
notifyWaitingThread(rospl);
|
||||
|
||||
} finally {
|
||||
poolLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies a waiting thread that a connection is available.
|
||||
* This will wake a thread waiting in the specific route pool,
|
||||
* if there is one.
|
||||
* Otherwise, a thread in the connection pool will be notified.
|
||||
*
|
||||
* @param rospl the pool in which to notify, or <code>null</code>
|
||||
*/
|
||||
protected void notifyWaitingThread(final RouteSpecificPool rospl) {
|
||||
|
||||
//@@@ while this strategy provides for best connection re-use,
|
||||
//@@@ is it fair? only do this if the connection is open?
|
||||
// Find the thread we are going to notify. We want to ensure that
|
||||
// each waiting thread is only interrupted once, so we will remove
|
||||
// it from all wait queues before interrupting.
|
||||
WaitingThread waitingThread = null;
|
||||
|
||||
poolLock.lock();
|
||||
try {
|
||||
|
||||
if ((rospl != null) && rospl.hasThread()) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Notifying thread waiting on pool" +
|
||||
" [" + rospl.getRoute() + "]");
|
||||
}
|
||||
waitingThread = rospl.nextThread();
|
||||
} else if (!waitingThreads.isEmpty()) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Notifying thread waiting on any pool");
|
||||
}
|
||||
waitingThread = waitingThreads.remove();
|
||||
} else if (log.isDebugEnabled()) {
|
||||
log.debug("Notifying no-one, there are no waiting threads");
|
||||
}
|
||||
|
||||
if (waitingThread != null) {
|
||||
waitingThread.wakeup();
|
||||
}
|
||||
|
||||
} finally {
|
||||
poolLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void deleteClosedConnections() {
|
||||
poolLock.lock();
|
||||
try {
|
||||
final Iterator<BasicPoolEntry> iter = freeConnections.iterator();
|
||||
while (iter.hasNext()) {
|
||||
final BasicPoolEntry entry = iter.next();
|
||||
if (!entry.getConnection().isOpen()) {
|
||||
iter.remove();
|
||||
deleteEntry(entry);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
poolLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes idle connections.
|
||||
*
|
||||
* @param idletime the time the connections should have been idle
|
||||
* in order to be closed now
|
||||
* @param tunit the unit for the <code>idletime</code>
|
||||
*/
|
||||
@Override
|
||||
public void closeIdleConnections(final long idletime, final TimeUnit tunit) {
|
||||
Args.notNull(tunit, "Time unit");
|
||||
final long t = idletime > 0 ? idletime : 0;
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Closing connections idle longer than " + t + " " + tunit);
|
||||
}
|
||||
// the latest time for which connections will be closed
|
||||
final long deadline = System.currentTimeMillis() - tunit.toMillis(t);
|
||||
poolLock.lock();
|
||||
try {
|
||||
final Iterator<BasicPoolEntry> iter = freeConnections.iterator();
|
||||
while (iter.hasNext()) {
|
||||
final BasicPoolEntry entry = iter.next();
|
||||
if (entry.getUpdated() <= deadline) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Closing connection last used @ " + new Date(entry.getUpdated()));
|
||||
}
|
||||
iter.remove();
|
||||
deleteEntry(entry);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
poolLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeExpiredConnections() {
|
||||
log.debug("Closing expired connections");
|
||||
final long now = System.currentTimeMillis();
|
||||
|
||||
poolLock.lock();
|
||||
try {
|
||||
final Iterator<BasicPoolEntry> iter = freeConnections.iterator();
|
||||
while (iter.hasNext()) {
|
||||
final BasicPoolEntry entry = iter.next();
|
||||
if (entry.isExpired(now)) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Closing connection expired @ " + new Date(entry.getExpiry()));
|
||||
}
|
||||
iter.remove();
|
||||
deleteEntry(entry);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
poolLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
poolLock.lock();
|
||||
try {
|
||||
if (shutdown) {
|
||||
return;
|
||||
}
|
||||
shutdown = true;
|
||||
|
||||
// close all connections that are issued to an application
|
||||
final Iterator<BasicPoolEntry> iter1 = leasedConnections.iterator();
|
||||
while (iter1.hasNext()) {
|
||||
final BasicPoolEntry entry = iter1.next();
|
||||
iter1.remove();
|
||||
closeConnection(entry);
|
||||
}
|
||||
|
||||
// close all free connections
|
||||
final Iterator<BasicPoolEntry> iter2 = freeConnections.iterator();
|
||||
while (iter2.hasNext()) {
|
||||
final BasicPoolEntry entry = iter2.next();
|
||||
iter2.remove();
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Closing connection"
|
||||
+ " [" + entry.getPlannedRoute() + "][" + entry.getState() + "]");
|
||||
}
|
||||
closeConnection(entry);
|
||||
}
|
||||
|
||||
// wake up all waiting threads
|
||||
final Iterator<WaitingThread> iwth = waitingThreads.iterator();
|
||||
while (iwth.hasNext()) {
|
||||
final WaitingThread waiter = iwth.next();
|
||||
iwth.remove();
|
||||
waiter.wakeup();
|
||||
}
|
||||
|
||||
routeToPool.clear();
|
||||
|
||||
} finally {
|
||||
poolLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* since 4.1
|
||||
*/
|
||||
public void setMaxTotalConnections(final int max) {
|
||||
poolLock.lock();
|
||||
try {
|
||||
maxTotalConnections = max;
|
||||
} finally {
|
||||
poolLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* since 4.1
|
||||
*/
|
||||
public int getMaxTotalConnections() {
|
||||
return maxTotalConnections;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
69
mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/PoolEntryRequest.java
vendored
Normal file
69
mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/PoolEntryRequest.java
vendored
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* 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 ch.boye.httpclientandroidlib.impl.conn.tsccm;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import ch.boye.httpclientandroidlib.conn.ConnectionPoolTimeoutException;
|
||||
|
||||
/**
|
||||
* Encapsulates a request for a {@link BasicPoolEntry}.
|
||||
*
|
||||
* @since 4.0
|
||||
*
|
||||
* @deprecated (4.2) use {@link java.util.concurrent.Future}
|
||||
*/
|
||||
@Deprecated
|
||||
public interface PoolEntryRequest {
|
||||
|
||||
/**
|
||||
* Obtains a pool entry with a connection within the given timeout.
|
||||
* If {@link #abortRequest()} is called before this completes
|
||||
* an {@link InterruptedException} is thrown.
|
||||
*
|
||||
* @param timeout the timeout, 0 or negative for no timeout
|
||||
* @param tunit the unit for the <code>timeout</code>,
|
||||
* may be <code>null</code> only if there is no timeout
|
||||
*
|
||||
* @return pool entry holding a connection for the route
|
||||
*
|
||||
* @throws ConnectionPoolTimeoutException
|
||||
* if the timeout expired
|
||||
* @throws InterruptedException
|
||||
* if the calling thread was interrupted or the request was aborted
|
||||
*/
|
||||
BasicPoolEntry getPoolEntry(
|
||||
long timeout,
|
||||
TimeUnit tunit) throws InterruptedException, ConnectionPoolTimeoutException;
|
||||
|
||||
/**
|
||||
* Aborts the active or next call to
|
||||
* {@link #getPoolEntry(long, TimeUnit)}.
|
||||
*/
|
||||
void abortRequest();
|
||||
|
||||
}
|
||||
313
mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/RouteSpecificPool.java
vendored
Normal file
313
mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/RouteSpecificPool.java
vendored
Normal file
|
|
@ -0,0 +1,313 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* 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 ch.boye.httpclientandroidlib.impl.conn.tsccm;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedList;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Queue;
|
||||
|
||||
import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
|
||||
/* LogFactory removed by HttpClient for Android script. */
|
||||
import ch.boye.httpclientandroidlib.conn.OperatedClientConnection;
|
||||
import ch.boye.httpclientandroidlib.conn.params.ConnPerRoute;
|
||||
import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
|
||||
import ch.boye.httpclientandroidlib.util.Args;
|
||||
import ch.boye.httpclientandroidlib.util.Asserts;
|
||||
import ch.boye.httpclientandroidlib.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.
|
||||
*
|
||||
* @since 4.0
|
||||
*
|
||||
* @deprecated (4.2) use {@link ch.boye.httpclientandroidlib.pool.AbstractConnPool}
|
||||
*/
|
||||
@Deprecated
|
||||
public class RouteSpecificPool {
|
||||
|
||||
public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass());
|
||||
|
||||
/** The route this pool is for. */
|
||||
protected final HttpRoute route; //Immutable
|
||||
|
||||
protected final int maxEntries;
|
||||
|
||||
/** Connections per route */
|
||||
protected final ConnPerRoute connPerRoute;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* @deprecated (4.1) use {@link RouteSpecificPool#RouteSpecificPool(HttpRoute, ConnPerRoute)}
|
||||
*/
|
||||
@Deprecated
|
||||
public RouteSpecificPool(final HttpRoute route, final int maxEntries) {
|
||||
this.route = route;
|
||||
this.maxEntries = maxEntries;
|
||||
this.connPerRoute = new ConnPerRoute() {
|
||||
public int getMaxForRoute(final HttpRoute route) {
|
||||
return RouteSpecificPool.this.maxEntries;
|
||||
}
|
||||
};
|
||||
this.freeEntries = new LinkedList<BasicPoolEntry>();
|
||||
this.waitingThreads = new LinkedList<WaitingThread>();
|
||||
this.numEntries = 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new route-specific pool.
|
||||
*
|
||||
* @param route the route for which to pool
|
||||
* @param connPerRoute the connections per route configuration
|
||||
*/
|
||||
public RouteSpecificPool(final HttpRoute route, final ConnPerRoute connPerRoute) {
|
||||
this.route = route;
|
||||
this.connPerRoute = connPerRoute;
|
||||
this.maxEntries = connPerRoute.getMaxForRoute(route);
|
||||
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 connPerRoute.getMaxForRoute(route) - 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()) {
|
||||
final ListIterator<BasicPoolEntry> it = freeEntries.listIterator(freeEntries.size());
|
||||
while (it.hasPrevious()) {
|
||||
final BasicPoolEntry entry = it.previous();
|
||||
if (entry.getState() == null || LangUtils.equals(state, entry.getState())) {
|
||||
it.remove();
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (getCapacity() == 0 && !freeEntries.isEmpty()) {
|
||||
final BasicPoolEntry entry = freeEntries.remove();
|
||||
entry.shutdownEntry();
|
||||
final OperatedClientConnection conn = entry.getConnection();
|
||||
try {
|
||||
conn.close();
|
||||
} catch (final 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(final 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(final BasicPoolEntry entry) {
|
||||
Args.check(route.equals(entry.getPlannedRoute()), "Entry not planned for this pool");
|
||||
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(final 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() {
|
||||
Asserts.check(numEntries > 0, "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(final WaitingThread wt) {
|
||||
Args.notNull(wt, "Waiting thread");
|
||||
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(final WaitingThread wt) {
|
||||
if (wt == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.waitingThreads.remove(wt);
|
||||
}
|
||||
|
||||
|
||||
} // class RouteSpecificPool
|
||||
|
|
@ -0,0 +1,377 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* 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 ch.boye.httpclientandroidlib.impl.conn.tsccm;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
|
||||
/* LogFactory removed by HttpClient for Android script. */
|
||||
import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
|
||||
import ch.boye.httpclientandroidlib.conn.ClientConnectionManager;
|
||||
import ch.boye.httpclientandroidlib.conn.ClientConnectionOperator;
|
||||
import ch.boye.httpclientandroidlib.conn.ClientConnectionRequest;
|
||||
import ch.boye.httpclientandroidlib.conn.ConnectionPoolTimeoutException;
|
||||
import ch.boye.httpclientandroidlib.conn.ManagedClientConnection;
|
||||
import ch.boye.httpclientandroidlib.conn.params.ConnPerRouteBean;
|
||||
import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
|
||||
import ch.boye.httpclientandroidlib.conn.scheme.SchemeRegistry;
|
||||
import ch.boye.httpclientandroidlib.impl.conn.DefaultClientConnectionOperator;
|
||||
import ch.boye.httpclientandroidlib.impl.conn.SchemeRegistryFactory;
|
||||
import ch.boye.httpclientandroidlib.params.HttpParams;
|
||||
import ch.boye.httpclientandroidlib.util.Args;
|
||||
import ch.boye.httpclientandroidlib.util.Asserts;
|
||||
|
||||
/**
|
||||
* Manages a pool of {@link ch.boye.httpclientandroidlib.conn.OperatedClientConnection }
|
||||
* and is able to service connection requests from multiple execution threads.
|
||||
* Connections are pooled on a per route basis. A request for a route which
|
||||
* already the manager has persistent connections for available in the pool
|
||||
* will be services by leasing a connection from the pool rather than
|
||||
* creating a brand new connection.
|
||||
* <p>
|
||||
* ThreadSafeClientConnManager maintains a maximum limit of connection on
|
||||
* a per route basis and in total. Per default this implementation will
|
||||
* create no more than than 2 concurrent connections per given route
|
||||
* and no more 20 connections in total. For many real-world applications
|
||||
* these limits may prove too constraining, especially if they use HTTP
|
||||
* as a transport protocol for their services. Connection limits, however,
|
||||
* can be adjusted using HTTP parameters.
|
||||
*
|
||||
* @since 4.0
|
||||
*
|
||||
* @deprecated (4.2) use {@link ch.boye.httpclientandroidlib.impl.conn.PoolingHttpClientConnectionManager}
|
||||
*/
|
||||
@ThreadSafe
|
||||
@Deprecated
|
||||
public class ThreadSafeClientConnManager implements ClientConnectionManager {
|
||||
|
||||
public HttpClientAndroidLog log;
|
||||
|
||||
/** The schemes supported by this connection manager. */
|
||||
protected final SchemeRegistry schemeRegistry; // @ThreadSafe
|
||||
|
||||
protected final AbstractConnPool connectionPool;
|
||||
|
||||
/** The pool of connections being managed. */
|
||||
protected final ConnPoolByRoute pool;
|
||||
|
||||
/** The operator for opening and updating connections. */
|
||||
protected final ClientConnectionOperator connOperator; // DefaultClientConnectionOperator is @ThreadSafe
|
||||
|
||||
protected final ConnPerRouteBean connPerRoute;
|
||||
|
||||
/**
|
||||
* Creates a new thread safe connection manager.
|
||||
*
|
||||
* @param schreg the scheme registry.
|
||||
*/
|
||||
public ThreadSafeClientConnManager(final SchemeRegistry schreg) {
|
||||
this(schreg, -1, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.1
|
||||
*/
|
||||
public ThreadSafeClientConnManager() {
|
||||
this(SchemeRegistryFactory.createDefault());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new thread safe connection manager.
|
||||
*
|
||||
* @param schreg the scheme registry.
|
||||
* @param connTTL max connection lifetime, <=0 implies "infinity"
|
||||
* @param connTTLTimeUnit TimeUnit of connTTL
|
||||
*
|
||||
* @since 4.1
|
||||
*/
|
||||
public ThreadSafeClientConnManager(final SchemeRegistry schreg,
|
||||
final long connTTL, final TimeUnit connTTLTimeUnit) {
|
||||
this(schreg, connTTL, connTTLTimeUnit, new ConnPerRouteBean());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new thread safe connection manager.
|
||||
*
|
||||
* @param schreg the scheme registry.
|
||||
* @param connTTL max connection lifetime, <=0 implies "infinity"
|
||||
* @param connTTLTimeUnit TimeUnit of connTTL
|
||||
* @param connPerRoute mapping of maximum connections per route,
|
||||
* provided as a dependency so it can be managed externally, e.g.
|
||||
* for dynamic connection pool size management.
|
||||
*
|
||||
* @since 4.2
|
||||
*/
|
||||
public ThreadSafeClientConnManager(final SchemeRegistry schreg,
|
||||
final long connTTL, final TimeUnit connTTLTimeUnit, final ConnPerRouteBean connPerRoute) {
|
||||
super();
|
||||
Args.notNull(schreg, "Scheme registry");
|
||||
this.log = new HttpClientAndroidLog(getClass());
|
||||
this.schemeRegistry = schreg;
|
||||
this.connPerRoute = connPerRoute;
|
||||
this.connOperator = createConnectionOperator(schreg);
|
||||
this.pool = createConnectionPool(connTTL, connTTLTimeUnit) ;
|
||||
this.connectionPool = this.pool;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new thread safe connection manager.
|
||||
*
|
||||
* @param params the parameters for this manager.
|
||||
* @param schreg the scheme registry.
|
||||
*
|
||||
* @deprecated (4.1) use {@link ThreadSafeClientConnManager#ThreadSafeClientConnManager(SchemeRegistry)}
|
||||
*/
|
||||
@Deprecated
|
||||
public ThreadSafeClientConnManager(final HttpParams params,
|
||||
final SchemeRegistry schreg) {
|
||||
Args.notNull(schreg, "Scheme registry");
|
||||
this.log = new HttpClientAndroidLog(getClass());
|
||||
this.schemeRegistry = schreg;
|
||||
this.connPerRoute = new ConnPerRouteBean();
|
||||
this.connOperator = createConnectionOperator(schreg);
|
||||
this.pool = (ConnPoolByRoute) createConnectionPool(params) ;
|
||||
this.connectionPool = this.pool;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
try {
|
||||
shutdown();
|
||||
} finally {
|
||||
super.finalize();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook for creating the connection pool.
|
||||
*
|
||||
* @return the connection pool to use
|
||||
*
|
||||
* @deprecated (4.1) use #createConnectionPool(long, TimeUnit))
|
||||
*/
|
||||
@Deprecated
|
||||
protected AbstractConnPool createConnectionPool(final HttpParams params) {
|
||||
return new ConnPoolByRoute(connOperator, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook for creating the connection pool.
|
||||
*
|
||||
* @return the connection pool to use
|
||||
*
|
||||
* @since 4.1
|
||||
*/
|
||||
protected ConnPoolByRoute createConnectionPool(final long connTTL, final TimeUnit connTTLTimeUnit) {
|
||||
return new ConnPoolByRoute(connOperator, connPerRoute, 20, connTTL, connTTLTimeUnit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook for creating the connection operator.
|
||||
* It is called by the constructor.
|
||||
* Derived classes can override this method to change the
|
||||
* instantiation of the operator.
|
||||
* The default implementation here instantiates
|
||||
* {@link DefaultClientConnectionOperator DefaultClientConnectionOperator}.
|
||||
*
|
||||
* @param schreg the scheme registry.
|
||||
*
|
||||
* @return the connection operator to use
|
||||
*/
|
||||
protected ClientConnectionOperator
|
||||
createConnectionOperator(final SchemeRegistry schreg) {
|
||||
|
||||
return new DefaultClientConnectionOperator(schreg);// @ThreadSafe
|
||||
}
|
||||
|
||||
public SchemeRegistry getSchemeRegistry() {
|
||||
return this.schemeRegistry;
|
||||
}
|
||||
|
||||
public ClientConnectionRequest requestConnection(
|
||||
final HttpRoute route,
|
||||
final Object state) {
|
||||
|
||||
final PoolEntryRequest poolRequest = pool.requestPoolEntry(
|
||||
route, state);
|
||||
|
||||
return new ClientConnectionRequest() {
|
||||
|
||||
public void abortRequest() {
|
||||
poolRequest.abortRequest();
|
||||
}
|
||||
|
||||
public ManagedClientConnection getConnection(
|
||||
final long timeout, final TimeUnit tunit) throws InterruptedException,
|
||||
ConnectionPoolTimeoutException {
|
||||
Args.notNull(route, "Route");
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Get connection: " + route + ", timeout = " + timeout);
|
||||
}
|
||||
|
||||
final BasicPoolEntry entry = poolRequest.getPoolEntry(timeout, tunit);
|
||||
return new BasicPooledConnAdapter(ThreadSafeClientConnManager.this, entry);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
public void releaseConnection(final ManagedClientConnection conn, final long validDuration, final TimeUnit timeUnit) {
|
||||
Args.check(conn instanceof BasicPooledConnAdapter, "Connection class mismatch, " +
|
||||
"connection not obtained from this manager");
|
||||
final BasicPooledConnAdapter hca = (BasicPooledConnAdapter) conn;
|
||||
if (hca.getPoolEntry() != null) {
|
||||
Asserts.check(hca.getManager() == this, "Connection not obtained from this manager");
|
||||
}
|
||||
synchronized (hca) {
|
||||
final BasicPoolEntry entry = (BasicPoolEntry) hca.getPoolEntry();
|
||||
if (entry == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
// make sure that the response has been read completely
|
||||
if (hca.isOpen() && !hca.isMarkedReusable()) {
|
||||
// In MTHCM, there would be a call to
|
||||
// SimpleHttpConnectionManager.finishLastResponse(conn);
|
||||
// Consuming the response is handled outside in 4.0.
|
||||
|
||||
// make sure this connection will not be re-used
|
||||
// Shut down rather than close, we might have gotten here
|
||||
// because of a shutdown trigger.
|
||||
// Shutdown of the adapter also clears the tracked route.
|
||||
hca.shutdown();
|
||||
}
|
||||
} catch (final IOException iox) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Exception shutting down released connection.",
|
||||
iox);
|
||||
}
|
||||
} finally {
|
||||
final boolean reusable = hca.isMarkedReusable();
|
||||
if (log.isDebugEnabled()) {
|
||||
if (reusable) {
|
||||
log.debug("Released connection is reusable.");
|
||||
} else {
|
||||
log.debug("Released connection is not reusable.");
|
||||
}
|
||||
}
|
||||
hca.detach();
|
||||
pool.freeEntry(entry, reusable, validDuration, timeUnit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
log.debug("Shutting down");
|
||||
pool.shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the total number of pooled connections for the given route.
|
||||
* This is the total number of connections that have been created and
|
||||
* are still in use by this connection manager for the route.
|
||||
* This value will not exceed the maximum number of connections per host.
|
||||
*
|
||||
* @param route the route in question
|
||||
*
|
||||
* @return the total number of pooled connections for that route
|
||||
*/
|
||||
public int getConnectionsInPool(final HttpRoute route) {
|
||||
return pool.getConnectionsInPool(route);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the total number of pooled connections. This is the total number of
|
||||
* connections that have been created and are still in use by this connection
|
||||
* manager. This value will not exceed the maximum number of connections
|
||||
* in total.
|
||||
*
|
||||
* @return the total number of pooled connections
|
||||
*/
|
||||
public int getConnectionsInPool() {
|
||||
return pool.getConnectionsInPool();
|
||||
}
|
||||
|
||||
public void closeIdleConnections(final long idleTimeout, final TimeUnit tunit) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Closing connections idle longer than " + idleTimeout + " " + tunit);
|
||||
}
|
||||
pool.closeIdleConnections(idleTimeout, tunit);
|
||||
}
|
||||
|
||||
public void closeExpiredConnections() {
|
||||
log.debug("Closing expired connections");
|
||||
pool.closeExpiredConnections();
|
||||
}
|
||||
|
||||
/**
|
||||
* since 4.1
|
||||
*/
|
||||
public int getMaxTotal() {
|
||||
return pool.getMaxTotalConnections();
|
||||
}
|
||||
|
||||
/**
|
||||
* since 4.1
|
||||
*/
|
||||
public void setMaxTotal(final int max) {
|
||||
pool.setMaxTotalConnections(max);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.1
|
||||
*/
|
||||
public int getDefaultMaxPerRoute() {
|
||||
return connPerRoute.getDefaultMaxPerRoute();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.1
|
||||
*/
|
||||
public void setDefaultMaxPerRoute(final int max) {
|
||||
connPerRoute.setDefaultMaxPerRoute(max);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.1
|
||||
*/
|
||||
public int getMaxForRoute(final HttpRoute route) {
|
||||
return connPerRoute.getMaxForRoute(route);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.1
|
||||
*/
|
||||
public void setMaxForRoute(final HttpRoute route, final int max) {
|
||||
connPerRoute.setMaxForRoute(route, max);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
198
mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/WaitingThread.java
vendored
Normal file
198
mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/WaitingThread.java
vendored
Normal file
|
|
@ -0,0 +1,198 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* 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 ch.boye.httpclientandroidlib.impl.conn.tsccm;
|
||||
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.concurrent.locks.Condition;
|
||||
|
||||
import ch.boye.httpclientandroidlib.util.Args;
|
||||
|
||||
/**
|
||||
* Represents a thread waiting for a connection.
|
||||
* This class implements throwaway objects. It is instantiated whenever
|
||||
* a thread needs to wait. Instances are not re-used, except if the
|
||||
* waiting thread experiences a spurious wakeup and continues to wait.
|
||||
* <br/>
|
||||
* All methods assume external synchronization on the condition
|
||||
* passed to the constructor.
|
||||
* Instances of this class do <i>not</i> synchronize access!
|
||||
*
|
||||
*
|
||||
* @since 4.0
|
||||
*
|
||||
* @deprecated (4.2) do not use
|
||||
*/
|
||||
@Deprecated
|
||||
public class WaitingThread {
|
||||
|
||||
/** The condition on which the thread is waiting. */
|
||||
private final Condition cond;
|
||||
|
||||
/** The route specific pool on which the thread is waiting. */
|
||||
//@@@ replace with generic pool interface
|
||||
private final RouteSpecificPool pool;
|
||||
|
||||
/** The thread that is waiting for an entry. */
|
||||
private Thread waiter;
|
||||
|
||||
/** True if this was interrupted. */
|
||||
private boolean aborted;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new entry for a waiting thread.
|
||||
*
|
||||
* @param cond the condition for which to wait
|
||||
* @param pool the pool on which the thread will be waiting,
|
||||
* or <code>null</code>
|
||||
*/
|
||||
public WaitingThread(final Condition cond, final RouteSpecificPool pool) {
|
||||
|
||||
Args.notNull(cond, "Condition");
|
||||
|
||||
this.cond = cond;
|
||||
this.pool = pool;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Obtains the condition.
|
||||
*
|
||||
* @return the condition on which to wait, never <code>null</code>
|
||||
*/
|
||||
public final Condition getCondition() {
|
||||
// not synchronized
|
||||
return this.cond;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Obtains the pool, if there is one.
|
||||
*
|
||||
* @return the pool on which a thread is or was waiting,
|
||||
* or <code>null</code>
|
||||
*/
|
||||
public final RouteSpecificPool getPool() {
|
||||
// not synchronized
|
||||
return this.pool;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Obtains the thread, if there is one.
|
||||
*
|
||||
* @return the thread which is waiting, or <code>null</code>
|
||||
*/
|
||||
public final Thread getThread() {
|
||||
// not synchronized
|
||||
return this.waiter;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Blocks the calling thread.
|
||||
* This method returns when the thread is notified or interrupted,
|
||||
* if a timeout occurrs, or if there is a spurious wakeup.
|
||||
* <br/>
|
||||
* This method assumes external synchronization.
|
||||
*
|
||||
* @param deadline when to time out, or <code>null</code> for no timeout
|
||||
*
|
||||
* @return <code>true</code> if the condition was satisfied,
|
||||
* <code>false</code> in case of a timeout.
|
||||
* Typically, a call to {@link #wakeup} is used to indicate
|
||||
* that the condition was satisfied. Since the condition is
|
||||
* accessible outside, this cannot be guaranteed though.
|
||||
*
|
||||
* @throws InterruptedException if the waiting thread was interrupted
|
||||
*
|
||||
* @see #wakeup
|
||||
*/
|
||||
public boolean await(final Date deadline)
|
||||
throws InterruptedException {
|
||||
|
||||
// This is only a sanity check. We cannot synchronize here,
|
||||
// the lock would not be released on calling cond.await() below.
|
||||
if (this.waiter != null) {
|
||||
throw new IllegalStateException
|
||||
("A thread is already waiting on this object." +
|
||||
"\ncaller: " + Thread.currentThread() +
|
||||
"\nwaiter: " + this.waiter);
|
||||
}
|
||||
|
||||
if (aborted) {
|
||||
throw new InterruptedException("Operation interrupted");
|
||||
}
|
||||
|
||||
this.waiter = Thread.currentThread();
|
||||
|
||||
boolean success = false;
|
||||
try {
|
||||
if (deadline != null) {
|
||||
success = this.cond.awaitUntil(deadline);
|
||||
} else {
|
||||
this.cond.await();
|
||||
success = true;
|
||||
}
|
||||
if (aborted) {
|
||||
throw new InterruptedException("Operation interrupted");
|
||||
}
|
||||
} finally {
|
||||
this.waiter = null;
|
||||
}
|
||||
return success;
|
||||
|
||||
} // await
|
||||
|
||||
|
||||
/**
|
||||
* Wakes up the waiting thread.
|
||||
* <br/>
|
||||
* This method assumes external synchronization.
|
||||
*/
|
||||
public void wakeup() {
|
||||
|
||||
// If external synchronization and pooling works properly,
|
||||
// this cannot happen. Just a sanity check.
|
||||
if (this.waiter == null) {
|
||||
throw new IllegalStateException
|
||||
("Nobody waiting on this object.");
|
||||
}
|
||||
|
||||
// One condition might be shared by several WaitingThread instances.
|
||||
// It probably isn't, but just in case: wake all, not just one.
|
||||
this.cond.signalAll();
|
||||
}
|
||||
|
||||
public void interrupt() {
|
||||
aborted = true;
|
||||
this.cond.signalAll();
|
||||
}
|
||||
|
||||
|
||||
} // class WaitingThread
|
||||
69
mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/WaitingThreadAborter.java
vendored
Normal file
69
mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/WaitingThreadAborter.java
vendored
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* 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 ch.boye.httpclientandroidlib.impl.conn.tsccm;
|
||||
|
||||
/**
|
||||
* A simple class that can interrupt a {@link WaitingThread}.
|
||||
*
|
||||
* Must be called with the pool lock held.
|
||||
*
|
||||
* @since 4.0
|
||||
*
|
||||
* @deprecated (4.2) do not use
|
||||
*/
|
||||
@Deprecated
|
||||
public class WaitingThreadAborter {
|
||||
|
||||
private WaitingThread waitingThread;
|
||||
private boolean aborted;
|
||||
|
||||
/**
|
||||
* If a waiting thread has been set, interrupts it.
|
||||
*/
|
||||
public void abort() {
|
||||
aborted = true;
|
||||
|
||||
if (waitingThread != null) {
|
||||
waitingThread.interrupt();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the waiting thread. If this has already been aborted,
|
||||
* the waiting thread is immediately interrupted.
|
||||
*
|
||||
* @param waitingThread The thread to interrupt when aborting.
|
||||
*/
|
||||
public void setWaitingThread(final WaitingThread waitingThread) {
|
||||
this.waitingThread = waitingThread;
|
||||
if (aborted) {
|
||||
waitingThread.interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
33
mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/package-info.java
vendored
Normal file
33
mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/package-info.java
vendored
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Deprecated.
|
||||
*
|
||||
* @deprecated (4.3)
|
||||
*/
|
||||
package ch.boye.httpclientandroidlib.impl.conn.tsccm;
|
||||
Loading…
Add table
Add a link
Reference in a new issue