/* $Id$ */
/**
* 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.
*/
package org.apache.manifoldcf.connectorcommon.interfaces;
import java.util.*;
/** An IConnectionThrottler object is not thread-local. It gates connection
* creation and pool management.
* The underlying model is a pool of connections. A connection gets pulled off the pool and
* used to perform a fetch. If there are insufficient connections in the pool, and there is
* sufficient capacity to create a new connection, a connection will be created instead.
* When the fetch is done, the connection is returned, and then there is a decision whether
* or not to put the connection back into the pool, or to destroy it. Finally, the pool is
* periodically evaluated, and connections may be destroyed if either they have expired,
* or the allocated connections are still over capacity.
*
* This object does not in itself contain a connection pool - but it is intended to assist
* in the management of that pool. Specifically, it tracks connections that are in the
* pool, and connections that are handed out for use, and performs ALL the waiting needed
* due to the pool being empty and/or the number of active connections being at or over
* the quota.
*/
public interface IConnectionThrottler
{
public static final String _rcsid = "@(#)$Id$";
// For grabbing a connection for use
/** Get the connection from the pool */
public final static int CONNECTION_FROM_POOL = 0;
/** Create a connection */
public final static int CONNECTION_FROM_CREATION = 1;
/** Pool shutting down */
public final static int CONNECTION_FROM_NOWHERE = -1;
/** Get permission to grab a connection for use. If this object believes there is a connection
* available in the pool, it will update its pool size variable and return If not, this method
* evaluates whether a new connection should be created. If neither condition is true, it
* waits until a connection is available.
*@return whether to take the connection from the pool, or create one, or whether the
* throttler is being shut down.
*/
public int waitConnectionAvailable()
throws InterruptedException;
/** Get permission to grab a connection for use. If this object believes there is a connection
* available in the pool, it will update its pool size variable and return If not, this method
* evaluates whether a new connection should be created. If neither condition is true, it
* waits until a connection is available.
*@return whether to take the connection from the pool, or create one, or whether the
* throttler is being shut down.
*/
public int waitConnectionAvailable(IBreakCheck breakCheck)
throws InterruptedException, BreakException;
/** For a new connection, obtain the fetch throttler to use for the connection.
* If the result from waitConnectionAvailable() is CONNECTION_FROM_CREATION,
* the calling code is expected to create a connection using the result of this method.
*@return the fetch throttler for a new connection.
*/
public IFetchThrottler getNewConnectionFetchThrottler();
/** This method indicates whether a formerly in-use connection should be placed back
* in the pool or destroyed.
*@return true if the connection should not be put into the pool but should instead
* simply be destroyed. If true is returned, the caller MUST call noteConnectionDestroyed()
* after the connection is destroyed in order for the bookkeeping to work. If false
* is returned, the caller MUST call noteConnectionReturnedToPool() after the connection
* is returned to the pool.
*/
public boolean noteReturnedConnection();
/** This method calculates whether a connection should be taken from the pool and destroyed
/* in order to meet quota requirements. If this method returns
/* true, you MUST remove a connection from the pool, and you MUST call
/* noteConnectionDestroyed() afterwards.
*@return true if a pooled connection should be destroyed. If true is returned, the
* caller MUST call noteConnectionDestroyed() (below) in order for the bookkeeping to work.
*/
public boolean checkDestroyPooledConnection();
/** Connection expiration is tricky, because even though a connection may be identified as
* being expired, at the very same moment it could be handed out in another thread. So there
* is a natural race condition present.
* The way the connection throttler deals with that is to allow the caller to reserve a connection
* for expiration. This must be called BEFORE the actual identified connection is removed from the
* connection pool. If the value returned by this method is "true", then a connection MUST be removed
* from the pool and destroyed, whether or not the identified connection is actually still available for
* destruction or not.
*@return true if a connection from the pool can be expired. If true is returned, noteConnectionDestruction()
* MUST be called once the connection has actually been destroyed.
*/
public boolean checkExpireConnection();
/** Note that a connection has been returned to the pool. Call this method after a connection has been
* placed back into the pool and is available for use.
*/
public void noteConnectionReturnedToPool();
/** Note that a connection has been destroyed. Call this method ONLY after noteReturnedConnection()
* or checkDestroyPooledConnection() returns true, AND the connection has been already
* destroyed.
*/
public void noteConnectionDestroyed();
}