edu.vt.middleware.ldap.pool.SharedLdapPool Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of vt-ldap Show documentation
Show all versions of vt-ldap Show documentation
Library for performing common LDAP operations
/*
$Id: SharedLdapPool.java 1330 2010-05-23 22:10:53Z dfisher $
Copyright (C) 2003-2010 Virginia Tech.
All rights reserved.
SEE LICENSE FOR MORE INFORMATION
Author: Middleware Services
Email: [email protected]
Version: $Revision: 1330 $
Updated: $Date: 2010-05-23 18:10:53 -0400 (Sun, 23 May 2010) $
*/
package edu.vt.middleware.ldap.pool;
import java.util.NoSuchElementException;
import edu.vt.middleware.ldap.Ldap;
/**
* SharedLdapPool
implements a pool of ldap objects that has a set
* minimum and maximum size. The pool will not grow beyond the maximum size and
* when the pool is exhausted, requests for new objects will be serviced by
* objects that are already in use. Since {@link edu.vt.middleware.ldap.Ldap} is
* a thread safe object this implementation leverages that by sharing ldap
* objects among requests. See {@link
* javax.naming.ldap.LdapContext#newInstance(Control[])}. This implementation
* should be used when you want some control over the maximum number of ldap
* connections, but can tolerate some new connections under high load. See
* {@link AbstractLdapPool}.
*
* @author Middleware Services
* @version $Revision: 1330 $ $Date: 2010-05-23 18:10:53 -0400 (Sun, 23 May 2010) $
*/
public class SharedLdapPool extends AbstractLdapPool
{
/** Creates a new ldap pool using {@link DefaultLdapFactory}. */
public SharedLdapPool()
{
super(new LdapPoolConfig(), new DefaultLdapFactory());
}
/**
* Creates a new ldap pool with the supplied ldap factory.
*
* @param lf ldap factory
*/
public SharedLdapPool(final LdapFactory lf)
{
super(new LdapPoolConfig(), lf);
}
/**
* Creates a new ldap pool with the supplied ldap config and factory.
*
* @param lpc ldap pool configuration
* @param lf ldap factory
*/
public SharedLdapPool(final LdapPoolConfig lpc, final LdapFactory lf)
{
super(lpc, lf);
}
/** {@inheritDoc} */
public Ldap checkOut()
throws LdapPoolException
{
Ldap l = null;
boolean create = false;
if (this.logger.isTraceEnabled()) {
this.logger.trace(
"waiting on pool lock for check out " + this.poolLock.getQueueLength());
}
this.poolLock.lock();
try {
// if an available object exists, use it
// if no available objects and the pool can grow, attempt to create
// otherwise the pool is full, return a shared object
if (this.active.size() < this.available.size()) {
if (this.logger.isTraceEnabled()) {
this.logger.trace("retrieve available ldap object");
}
l = this.retrieveAvailable();
} else if (this.active.size() < this.poolConfig.getMaxPoolSize()) {
if (this.logger.isTraceEnabled()) {
this.logger.trace("pool can grow, attempt to create ldap object");
}
create = true;
} else {
if (this.logger.isTraceEnabled()) {
this.logger.trace(
"pool is full, " +
"attempt to retrieve available ldap object");
}
l = this.retrieveAvailable();
}
} finally {
this.poolLock.unlock();
}
if (create) {
// previous block determined a creation should occur
// block here until create occurs without locking the whole pool
// if the pool is already maxed or creates are failing,
// return a shared object
this.checkOutLock.lock();
try {
boolean b = true;
this.poolLock.lock();
try {
if (this.available.size() == this.poolConfig.getMaxPoolSize()) {
b = false;
}
} finally {
this.poolLock.unlock();
}
if (b) {
l = this.createAvailableAndActive();
if (this.logger.isTraceEnabled()) {
this.logger.trace(
"created new available and active ldap object: " + l);
}
}
} finally {
this.checkOutLock.unlock();
}
if (l == null) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("create failed, retrieve available ldap object");
}
l = this.retrieveAvailable();
}
}
if (l != null) {
this.activateAndValidate(l);
} else {
if (this.logger.isErrorEnabled()) {
this.logger.error("Could not service check out request");
}
throw new LdapPoolExhaustedException(
"Pool is empty and object creation failed");
}
return l;
}
/**
* This attempts to retrieve an ldap object from the available queue. This
* pooling implementation guarantees there is always an object available.
*
* @return ldap object from the pool
*
* @throws IllegalStateException if an object cannot be removed from the
* available queue
*/
protected Ldap retrieveAvailable()
{
Ldap l = null;
if (this.logger.isTraceEnabled()) {
this.logger.trace(
"waiting on pool lock for retrieve available " +
this.poolLock.getQueueLength());
}
this.poolLock.lock();
try {
try {
final PooledLdap pl = this.available.remove();
this.active.add(new PooledLdap(pl.getLdap()));
this.available.add(new PooledLdap(pl.getLdap()));
l = pl.getLdap();
if (this.logger.isTraceEnabled()) {
this.logger.trace("retrieved available ldap object: " + l);
}
} catch (NoSuchElementException e) {
if (this.logger.isErrorEnabled()) {
this.logger.error("could not remove ldap object from list", e);
}
throw new IllegalStateException("Pool is empty", e);
}
} finally {
this.poolLock.unlock();
}
return l;
}
/** {@inheritDoc} */
public void checkIn(final Ldap l)
{
final boolean valid = this.validateAndPassivate(l);
final PooledLdap pl = new PooledLdap(l);
if (this.logger.isTraceEnabled()) {
this.logger.trace(
"waiting on pool lock for check in " + this.poolLock.getQueueLength());
}
this.poolLock.lock();
try {
if (this.active.remove(pl)) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("returned active ldap object: " + l);
}
} else if (this.available.contains(pl)) {
if (this.logger.isWarnEnabled()) {
this.logger.warn("returned available ldap object: " + l);
}
} else {
if (this.logger.isWarnEnabled()) {
this.logger.warn("attempt to return unknown ldap object: " + l);
}
}
if (!valid) {
this.available.remove(pl);
}
} finally {
this.poolLock.unlock();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy