Return-Path: X-Original-To: apmail-directory-commits-archive@www.apache.org Delivered-To: apmail-directory-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 6E8ED1740E for ; Wed, 5 Nov 2014 23:17:41 +0000 (UTC) Received: (qmail 17573 invoked by uid 500); 5 Nov 2014 23:17:41 -0000 Delivered-To: apmail-directory-commits-archive@directory.apache.org Received: (qmail 17538 invoked by uid 500); 5 Nov 2014 23:17:41 -0000 Mailing-List: contact commits-help@directory.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@directory.apache.org Delivered-To: mailing list commits@directory.apache.org Received: (qmail 17529 invoked by uid 99); 5 Nov 2014 23:17:41 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 05 Nov 2014 23:17:41 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 05 Nov 2014 23:17:14 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id CD8B523889EB; Wed, 5 Nov 2014 23:17:11 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1637004 - in /directory: apacheds/trunk/ldap-client-test/src/test/java/org/apache/directory/ldap/client/template/ apacheds/trunk/ldap-client-test/src/test/java/org/apache/directory/shared/client/api/ apacheds/trunk/test-framework/src/main/... Date: Wed, 05 Nov 2014 23:17:11 -0000 To: commits@directory.apache.org From: elecharny@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20141105231711.CD8B523889EB@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: elecharny Date: Wed Nov 5 23:17:10 2014 New Revision: 1637004 URL: http://svn.apache.org/r1637004 Log: o Created a Lightweight Poolable config that does not validate the connection, nor it is binding them when they are released. It goes 3 times faster than the standard config. This is the DefaultPooleableLdapConnectionfactory class. o Renamed the PoolableLdapConnectionFactory to ValidatingPooleableConnectionFactory o Created an Abstract class that is the root of the two previous classes o Used the default pool factory for the tests Added: directory/apacheds/trunk/ldap-client-test/src/test/java/org/apache/directory/shared/client/api/LightweightLdapConnectionPoolTest.java directory/shared/trunk/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/AbstractPoolableLdapConnectionFactory.java directory/shared/trunk/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/DefaultPoolableLdapConnectionFactory.java directory/shared/trunk/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/ValidatingPoolableLdapConnectionFactory.java - copied, changed from r1636845, directory/shared/trunk/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/PoolableLdapConnectionFactory.java Removed: directory/shared/trunk/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/PoolableLdapConnectionFactory.java Modified: directory/apacheds/trunk/ldap-client-test/src/test/java/org/apache/directory/ldap/client/template/LdapConnectionTemplateTest.java directory/apacheds/trunk/ldap-client-test/src/test/java/org/apache/directory/shared/client/api/LdapConnectionPoolTest.java directory/apacheds/trunk/test-framework/src/main/java/org/apache/directory/server/core/integ/CreateLdapConnectionPoolRule.java directory/shared/trunk/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/LdapConnectionPool.java Modified: directory/apacheds/trunk/ldap-client-test/src/test/java/org/apache/directory/ldap/client/template/LdapConnectionTemplateTest.java URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/ldap-client-test/src/test/java/org/apache/directory/ldap/client/template/LdapConnectionTemplateTest.java?rev=1637004&r1=1637003&r2=1637004&view=diff ============================================================================== --- directory/apacheds/trunk/ldap-client-test/src/test/java/org/apache/directory/ldap/client/template/LdapConnectionTemplateTest.java (original) +++ directory/apacheds/trunk/ldap-client-test/src/test/java/org/apache/directory/ldap/client/template/LdapConnectionTemplateTest.java Wed Nov 5 23:17:10 2014 @@ -43,7 +43,7 @@ import org.apache.directory.api.ldap.mod import org.apache.directory.ldap.client.api.DefaultLdapConnectionFactory; import org.apache.directory.ldap.client.api.LdapConnectionConfig; import org.apache.directory.ldap.client.api.LdapConnectionPool; -import org.apache.directory.ldap.client.api.PoolableLdapConnectionFactory; +import org.apache.directory.ldap.client.api.ValidatingPoolableLdapConnectionFactory; import org.apache.directory.ldap.client.template.exception.PasswordException; import org.apache.directory.server.annotations.CreateLdapConnectionPool; import org.apache.directory.server.annotations.CreateLdapServer; @@ -367,7 +367,7 @@ public class LdapConnectionTemplateTest LdapConnectionTemplate ldapConnectionTemplate = new LdapConnectionTemplate( new LdapConnectionPool( - new PoolableLdapConnectionFactory( factory ), poolConfig ) ); + new ValidatingPoolableLdapConnectionFactory( factory ), poolConfig ) ); assertNotNull( ldapConnectionTemplate ); List muppets = ldapConnectionTemplate.search( Modified: directory/apacheds/trunk/ldap-client-test/src/test/java/org/apache/directory/shared/client/api/LdapConnectionPoolTest.java URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/ldap-client-test/src/test/java/org/apache/directory/shared/client/api/LdapConnectionPoolTest.java?rev=1637004&r1=1637003&r2=1637004&view=diff ============================================================================== --- directory/apacheds/trunk/ldap-client-test/src/test/java/org/apache/directory/shared/client/api/LdapConnectionPoolTest.java (original) +++ directory/apacheds/trunk/ldap-client-test/src/test/java/org/apache/directory/shared/client/api/LdapConnectionPoolTest.java Wed Nov 5 23:17:10 2014 @@ -25,13 +25,14 @@ import static org.junit.Assert.assertNot import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +import org.apache.commons.pool.PoolableObjectFactory; import org.apache.commons.pool.impl.GenericObjectPool; import org.apache.directory.api.ldap.model.name.Dn; import org.apache.directory.ldap.client.api.LdapConnection; import org.apache.directory.ldap.client.api.LdapConnectionConfig; import org.apache.directory.ldap.client.api.LdapConnectionPool; import org.apache.directory.ldap.client.api.LdapNetworkConnection; -import org.apache.directory.ldap.client.api.PoolableLdapConnectionFactory; +import org.apache.directory.ldap.client.api.ValidatingPoolableLdapConnectionFactory; import org.apache.directory.server.annotations.CreateLdapServer; import org.apache.directory.server.annotations.CreateTransport; import org.apache.directory.server.constants.ServerDNConstants; @@ -116,7 +117,7 @@ public class LdapConnectionPoolTest exte config.setLdapPort( port ); config.setName( DEFAULT_ADMIN ); config.setCredentials( DEFAULT_PASSWORD ); - PoolableLdapConnectionFactory factory = new PoolableLdapConnectionFactory( config ); + PoolableObjectFactory factory = new ValidatingPoolableLdapConnectionFactory( config ); pool = new LdapConnectionPool( factory ); pool.setTestOnBorrow( true ); pool.setWhenExhaustedAction( GenericObjectPool.WHEN_EXHAUSTED_GROW ); @@ -160,16 +161,21 @@ public class LdapConnectionPoolTest exte public void testRebind() throws Exception { LdapConnection connection = pool.getConnection(); - connection.bind( ServerDNConstants.ADMIN_SYSTEM_DN, "secret" ); + pool.releaseConnection( connection ); + + long t0 = System.currentTimeMillis(); + long t00 = t0; - for ( int i = 0; i < 30000; i++ ) + for ( int i = 0; i < 1000000; i++ ) { // First, unbind try { - if ( i % 100 == 0 ) + if ( i % 10000 == 0 ) { - System.out.println( "Iteration #" + i ); + long t01 = t00; + t00 = System.currentTimeMillis(); + System.out.println( "Iteration # " + i + " in " + ( t00 - t01 ) ); } connection.unBind(); @@ -202,6 +208,10 @@ public class LdapConnectionPoolTest exte } } + long t1 = System.currentTimeMillis(); + + System.out.println( "Time needed to bind/uinbind 10 000 connections : " + ( t1 - t0 ) ); + // terminate with an unbind try { @@ -227,7 +237,7 @@ public class LdapConnectionPoolTest exte LdapConnection connection = new LdapNetworkConnection( DEFAULT_HOST, getLdapServer().getPort() ); connection.bind( ServerDNConstants.ADMIN_SYSTEM_DN, "secret" ); - for ( int i = 0; i < 30000; i++ ) + for ( int i = 0; i < 10000; i++ ) { if ( i % 100 == 0 ) { @@ -282,7 +292,7 @@ public class LdapConnectionPoolTest exte config.setLdapPort( getLdapServer().getPort() ); config.setName( DEFAULT_ADMIN ); config.setCredentials( DEFAULT_PASSWORD ); - PoolableLdapConnectionFactory factory = new PoolableLdapConnectionFactory( config ); + ValidatingPoolableLdapConnectionFactory factory = new ValidatingPoolableLdapConnectionFactory( config ); LdapConnectionPool pool = new LdapConnectionPool( factory ); pool.setMaxActive( 1 ); pool.setTestOnBorrow( true ); Added: directory/apacheds/trunk/ldap-client-test/src/test/java/org/apache/directory/shared/client/api/LightweightLdapConnectionPoolTest.java URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/ldap-client-test/src/test/java/org/apache/directory/shared/client/api/LightweightLdapConnectionPoolTest.java?rev=1637004&view=auto ============================================================================== --- directory/apacheds/trunk/ldap-client-test/src/test/java/org/apache/directory/shared/client/api/LightweightLdapConnectionPoolTest.java (added) +++ directory/apacheds/trunk/ldap-client-test/src/test/java/org/apache/directory/shared/client/api/LightweightLdapConnectionPoolTest.java Wed Nov 5 23:17:10 2014 @@ -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. + * + */ +package org.apache.directory.shared.client.api; + + +import static org.junit.Assert.assertNotNull; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import org.apache.commons.pool.PoolableObjectFactory; +import org.apache.commons.pool.impl.GenericObjectPool; +import org.apache.directory.api.ldap.model.name.Dn; +import org.apache.directory.ldap.client.api.DefaultPoolableLdapConnectionFactory; +import org.apache.directory.ldap.client.api.LdapConnection; +import org.apache.directory.ldap.client.api.LdapConnectionConfig; +import org.apache.directory.ldap.client.api.LdapConnectionPool; +import org.apache.directory.ldap.client.api.LdapNetworkConnection; +import org.apache.directory.server.annotations.CreateLdapServer; +import org.apache.directory.server.annotations.CreateTransport; +import org.apache.directory.server.constants.ServerDNConstants; +import org.apache.directory.server.core.integ.AbstractLdapTestUnit; +import org.apache.directory.server.core.integ.FrameworkRunner; +import org.junit.After; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; + + +/** + * A test class for the connection pool. + * + * @author Apache Directory Project + */ +@RunWith(FrameworkRunner.class) +@CreateLdapServer(transports = + { @CreateTransport(protocol = "LDAP") }) +public class LightweightLdapConnectionPoolTest extends AbstractLdapTestUnit +{ + /** The connection pool */ + private LdapConnectionPool pool; + + /** The Constant DEFAULT_HOST. */ + private static final String DEFAULT_HOST = "localhost"; + + /** The Constant DEFAULT_ADMIN. */ + private static final String DEFAULT_ADMIN = ServerDNConstants.ADMIN_SYSTEM_DN; + + /** The Constant DEFAULT_PASSWORD. */ + private static final String DEFAULT_PASSWORD = "secret"; + + /** + * A thread used to test the connection + */ + private class ConnectionThread extends Thread + { + int threadNumber; + CountDownLatch counter; + + + public ConnectionThread( int threadNumber, CountDownLatch counter ) + { + this.threadNumber = threadNumber; + this.counter = counter; + } + + + @Override + public void run() + { + try + { + for ( int i = 0; i < 100; i++ ) + { + LdapConnection connection = pool.getConnection(); + + connection.lookup( Dn.ROOT_DSE, "1.1 " ); + + pool.releaseConnection( connection ); + + counter.countDown(); + } + } + catch ( Exception e ) + { + // Do nothing + } + } + } + + + @Before + public void setUp() throws Exception + { + int port = getLdapServer().getPort(); + + LdapConnectionConfig config = new LdapConnectionConfig(); + config.setLdapHost( "localHost" ); + config.setLdapPort( port ); + config.setName( DEFAULT_ADMIN ); + config.setCredentials( DEFAULT_PASSWORD ); + PoolableObjectFactory factory = new DefaultPoolableLdapConnectionFactory( config ); + pool = new LdapConnectionPool( factory ); + pool.setTestOnBorrow( true ); + pool.setWhenExhaustedAction( GenericObjectPool.WHEN_EXHAUSTED_GROW ); + } + + + @After + public void tearDown() throws Exception + { + pool.close(); + } + + + /** + * Test the creation of many connections + */ + @Test + public void testManyConnections() throws Exception + { + CountDownLatch counter = new CountDownLatch( 10000 ); + + long t0 = System.currentTimeMillis(); + + for ( int i = 0; i < 100; i++ ) + { + ConnectionThread thread = new ConnectionThread( i, counter ); + + thread.start(); + } + + boolean result = counter.await( 100, TimeUnit.SECONDS ); + + long t1 = System.currentTimeMillis(); + + System.out.println( "Time to create and use 10 000 connections = " + ( t1 - t0 ) ); + } + + + @Test + @Ignore + public void testRebind() throws Exception + { + LdapConnection connection = pool.getConnection(); + pool.releaseConnection( connection ); + + long t0 = System.currentTimeMillis(); + long t00 = t0; + + for ( int i = 0; i < 1000000; i++ ) + { + // First, unbind + try + { + if ( i % 10000 == 0 ) + { + long t01 = t00; + t00 = System.currentTimeMillis(); + System.out.println( "Iteration # " + i + " in " + ( t00 - t01 ) ); + } + + connection.unBind(); + } + catch ( Exception e ) + { + e.printStackTrace(); + throw e; + } + finally + { + assertNotNull( connection ); + pool.releaseConnection( connection ); + } + + // Then bind again + try + { + connection = pool.getConnection(); + connection.bind( ServerDNConstants.ADMIN_SYSTEM_DN, "secret" ); + } + catch ( Exception e ) + { + e.printStackTrace(); + throw e; + } + finally + { + assertNotNull( connection ); + } + } + + long t1 = System.currentTimeMillis(); + + System.out.println( "Time needed to bind/uinbind 10 000 connections : " + ( t1 - t0 ) ); + + // terminate with an unbind + try + { + connection.unBind(); + } + catch ( Exception e ) + { + e.printStackTrace(); + throw e; + } + finally + { + assertNotNull( connection ); + pool.releaseConnection( connection ); + } + } + + + @Test + @Ignore + public void testRebindNoPool() throws Exception + { + LdapConnection connection = new LdapNetworkConnection( DEFAULT_HOST, getLdapServer().getPort() ); + connection.bind( ServerDNConstants.ADMIN_SYSTEM_DN, "secret" ); + + long t0 = System.currentTimeMillis(); + + for ( int i = 0; i < 10000; i++ ) + { + if ( i % 100 == 0 ) + { + System.out.println( "Iteration # " + i ); + } + // First, unbind + try + { + connection.unBind(); + } + catch ( Exception e ) + { + e.printStackTrace(); + throw e; + } + + //Thread.sleep( 5 ); + + // Don't close the connection, we want to reuse it + // Then bind again + try + { + connection.bind( ServerDNConstants.ADMIN_SYSTEM_DN, "secret" ); + } + catch ( Exception e ) + { + System.out.println( "Failure after " + i + " iterations" ); + e.printStackTrace(); + throw e; + } + } + + long t1 = System.currentTimeMillis(); + + System.out.println( "Time needed to bind/uinbind 10 000 connections : " + ( t1 - t0 ) ); + + // terminate with an unbind + try + { + connection.unBind(); + } + catch ( Exception e ) + { + e.printStackTrace(); + } + + connection.close(); + } + + + @Test + public void testSmallPool() throws Exception + { + LdapConnectionConfig config = new LdapConnectionConfig(); + config.setLdapHost( "localHost" ); + config.setLdapPort( getLdapServer().getPort() ); + config.setName( DEFAULT_ADMIN ); + config.setCredentials( DEFAULT_PASSWORD ); + PoolableObjectFactory factory = new DefaultPoolableLdapConnectionFactory( config ); + LdapConnectionPool pool = new LdapConnectionPool( factory ); + pool.setMaxActive( 1 ); + pool.setTestOnBorrow( true ); + pool.setWhenExhaustedAction( GenericObjectPool.WHEN_EXHAUSTED_FAIL ); + + for ( int i = 0; i < 100; i++ ) + { + LdapConnection connection = pool.getConnection(); + pool.releaseConnection( connection ); + } + } +} Modified: directory/apacheds/trunk/test-framework/src/main/java/org/apache/directory/server/core/integ/CreateLdapConnectionPoolRule.java URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/test-framework/src/main/java/org/apache/directory/server/core/integ/CreateLdapConnectionPoolRule.java?rev=1637004&r1=1637003&r2=1637004&view=diff ============================================================================== --- directory/apacheds/trunk/test-framework/src/main/java/org/apache/directory/server/core/integ/CreateLdapConnectionPoolRule.java (original) +++ directory/apacheds/trunk/test-framework/src/main/java/org/apache/directory/server/core/integ/CreateLdapConnectionPoolRule.java Wed Nov 5 23:17:10 2014 @@ -22,9 +22,9 @@ package org.apache.directory.server.core import org.apache.commons.pool.impl.GenericObjectPool.Config; import org.apache.directory.api.ldap.codec.api.DefaultConfigurableBinaryAttributeDetector; import org.apache.directory.ldap.client.api.DefaultLdapConnectionFactory; +import org.apache.directory.ldap.client.api.DefaultPoolableLdapConnectionFactory; import org.apache.directory.ldap.client.api.LdapConnectionConfig; import org.apache.directory.ldap.client.api.LdapConnectionPool; -import org.apache.directory.ldap.client.api.PoolableLdapConnectionFactory; import org.apache.directory.ldap.client.template.LdapConnectionTemplate; import org.apache.directory.server.annotations.CreateLdapConnectionPool; import org.apache.directory.server.ldap.LdapServer; @@ -146,8 +146,9 @@ public class CreateLdapConnectionPoolRul config.setLdapPort( ldapServer.getPort() ); config.setName( "uid=admin,ou=system" ); config.setCredentials( "secret" ); - if ( createLdapConnectionPool.additionalBinaryAttributes() != null - && createLdapConnectionPool.additionalBinaryAttributes().length > 0 ) + + if ( ( createLdapConnectionPool.additionalBinaryAttributes() != null ) + && ( createLdapConnectionPool.additionalBinaryAttributes().length > 0 ) ) { DefaultConfigurableBinaryAttributeDetector binaryAttributeDetector = new DefaultConfigurableBinaryAttributeDetector(); @@ -180,7 +181,7 @@ public class CreateLdapConnectionPoolRul .whenExhaustedAction(); return new LdapConnectionPool( - new PoolableLdapConnectionFactory( factory ), poolConfig ); + new DefaultPoolableLdapConnectionFactory( factory ), poolConfig ); } @@ -192,8 +193,9 @@ public class CreateLdapConnectionPoolRul : classCreateLdapConnectionPoolRule.getLdapConnectionPool() ) : ldapConnectionPool; } - - public LdapConnectionTemplate getLdapConnectionTemplate() + + + public LdapConnectionTemplate getLdapConnectionTemplate() { return ldapConnectionTemplate == null ? ( classCreateLdapConnectionPoolRule == null Added: directory/shared/trunk/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/AbstractPoolableLdapConnectionFactory.java URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/AbstractPoolableLdapConnectionFactory.java?rev=1637004&view=auto ============================================================================== --- directory/shared/trunk/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/AbstractPoolableLdapConnectionFactory.java (added) +++ directory/shared/trunk/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/AbstractPoolableLdapConnectionFactory.java Wed Nov 5 23:17:10 2014 @@ -0,0 +1,49 @@ +/* + * 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.directory.ldap.client.api; + + +import org.apache.commons.pool.PoolableObjectFactory; +import org.apache.directory.api.ldap.codec.api.LdapApiService; + + +/** + * An abstract class implementing the PoolableObjectFactory, for LdapConnections. + * + * @author Apache Directory Project + */ +public abstract class AbstractPoolableLdapConnectionFactory implements PoolableObjectFactory +{ + + /** The factory to use to create a new connection */ + protected LdapConnectionFactory connectionFactory; + + + /** + * Returns the LdapApiService instance used by this factory. + * + * @return The LdapApiService instance used by this factory + */ + public LdapApiService getLdapApiService() + { + return connectionFactory.getLdapApiService(); + } +} Added: directory/shared/trunk/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/DefaultPoolableLdapConnectionFactory.java URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/DefaultPoolableLdapConnectionFactory.java?rev=1637004&view=auto ============================================================================== --- directory/shared/trunk/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/DefaultPoolableLdapConnectionFactory.java (added) +++ directory/shared/trunk/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/DefaultPoolableLdapConnectionFactory.java Wed Nov 5 23:17:10 2014 @@ -0,0 +1,181 @@ +/* + * 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.directory.ldap.client.api; + + +import java.io.IOException; + +import org.apache.directory.api.ldap.model.exception.LdapException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +/** + * A factory for creating LdapConnection objects managed by LdapConnectionPool. The connections are + * not validated when they are pulled from the pool : we just check if they are still connected, using + * their internal flag. We don't either re-bind when we push back teh connection into the pool. + *
+ * It's up to the users to be careful with the way they deal with connectiosn -especially when using + * the StartTLS extended operation -. + * + * @author Apache Directory Project + */ +public class DefaultPoolableLdapConnectionFactory extends AbstractPoolableLdapConnectionFactory +{ + /** This class logger */ + private static final Logger LOG = LoggerFactory.getLogger( DefaultPoolableLdapConnectionFactory.class ); + + + /** + * Creates a new instance of PoolableLdapConnectionFactory. + * + * @param config the configuration for creating LdapConnections + */ + public DefaultPoolableLdapConnectionFactory( LdapConnectionConfig config ) + { + this( new DefaultLdapConnectionFactory( config ) ); + } + + + /** + * Creates a new instance of PoolableLdapConnectionFactory. + * + * @param connectionFactory the connection factory for creating LdapConnections + */ + public DefaultPoolableLdapConnectionFactory( LdapConnectionFactory connectionFactory ) + { + this.connectionFactory = connectionFactory; + } + + + /** + * {@inheritDoc} + * + * There is nothing to do to activate a connection. + */ + public void activateObject( LdapConnection connection ) + { + LOG.debug( "Activating {}", connection ); + } + + + /** + * {@inheritDoc} + * + * Destroying a connection will unbind it which will result on a shutdown + * of the underlying protocol. + */ + public void destroyObject( LdapConnection connection ) + { + LOG.debug( "Destroying {}", connection ); + + if ( connection.isConnected() ) + { + try + { + connection.unBind(); + } + catch ( LdapException e ) + { + LOG.error( "unable to unbind connection: {}", e.getMessage() ); + LOG.debug( "unable to unbind connection:", e ); + } + } + + try + { + connection.close(); + } + catch ( IOException e ) + { + LOG.error( "unable to close connection: {}", e.getMessage() ); + LOG.debug( "unable to close connection:", e ); + } + } + + + /** + * {@inheritDoc} + * Specifically, we are creating a new connection based on the LdapConnection Factory + * we used to create this pool of connections. The default is to create bound connections. + * + * @throws LdapException If unable to connect. + */ + public LdapConnection makeObject() throws LdapException + { + LOG.debug( "Creating a LDAP connection" ); + + return connectionFactory.newLdapConnection(); + } + + + /** + * {@inheritDoc} + * + * We don't do anything with the connection. It remains in the state it was before + * being used. + * + * @throws LdapException If unable to reconfigure and rebind. + */ + public void passivateObject( LdapConnection connection ) throws LdapException + { + LOG.debug( "Passivating {}", connection ); + } + + + /** + * {@inheritDoc} + * + * Validating a connection is done by checking the connection status. We though + * re-bind if teh connection is connected but not authenticated. + */ + public boolean validateObject( LdapConnection connection ) + { + LOG.debug( "Validating {}", connection ); + + if ( connection.isConnected() ) + { + if ( connection.isAuthenticated() ) + { + return true; + } + else + { + // Not authenticated, let's do it + try + { + connectionFactory.bindConnection( connection ); + + return true; + } + catch ( LdapException le ) + { + return false; + } + } + } + else + { + // Not connected, get out + return false; + } + } +} Modified: directory/shared/trunk/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/LdapConnectionPool.java URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/LdapConnectionPool.java?rev=1637004&r1=1637003&r2=1637004&view=diff ============================================================================== --- directory/shared/trunk/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/LdapConnectionPool.java (original) +++ directory/shared/trunk/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/LdapConnectionPool.java Wed Nov 5 23:17:10 2014 @@ -21,6 +21,7 @@ package org.apache.directory.ldap.client.api; +import org.apache.commons.pool.PoolableObjectFactory; import org.apache.commons.pool.impl.GenericObjectPool; import org.apache.directory.api.ldap.codec.api.LdapApiService; import org.apache.directory.api.ldap.model.exception.LdapException; @@ -40,7 +41,7 @@ public class LdapConnectionPool extends { private static Logger LOG = LoggerFactory.getLogger( LdapConnectionPool.class ); - private PoolableLdapConnectionFactory factory; + private PoolableObjectFactory factory; /** @@ -77,7 +78,7 @@ public class LdapConnectionPool extends * * @param factory The LDAP connection factory */ - public LdapConnectionPool( PoolableLdapConnectionFactory factory ) + public LdapConnectionPool( PoolableObjectFactory factory ) { this( factory, null ); } @@ -89,7 +90,7 @@ public class LdapConnectionPool extends * @param factory The LDAP connection factory * @param poolConfig The pool configuration */ - public LdapConnectionPool( PoolableLdapConnectionFactory factory, Config poolConfig ) + public LdapConnectionPool( PoolableObjectFactory factory, Config poolConfig ) { super( factory, poolConfig == null ? new Config() : poolConfig ); this.factory = factory; @@ -103,7 +104,7 @@ public class LdapConnectionPool extends */ public LdapApiService getLdapApiService() { - return factory.getLdapApiService(); + return ( ( AbstractPoolableLdapConnectionFactory ) factory ).getLdapApiService(); } @@ -143,7 +144,7 @@ public class LdapConnectionPool extends } - private static PoolableLdapConnectionFactory newPoolableConnectionFactory( + private static ValidatingPoolableLdapConnectionFactory newPoolableConnectionFactory( LdapConnectionConfig connectionConfig, LdapApiService apiService, long timeout ) { @@ -151,7 +152,7 @@ public class LdapConnectionPool extends new DefaultLdapConnectionFactory( connectionConfig ); connectionFactory.setLdapApiService( apiService ); connectionFactory.setTimeOut( timeout ); - return new PoolableLdapConnectionFactory( connectionFactory ); + return new ValidatingPoolableLdapConnectionFactory( connectionFactory ); } Copied: directory/shared/trunk/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/ValidatingPoolableLdapConnectionFactory.java (from r1636845, directory/shared/trunk/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/PoolableLdapConnectionFactory.java) URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/ValidatingPoolableLdapConnectionFactory.java?p2=directory/shared/trunk/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/ValidatingPoolableLdapConnectionFactory.java&p1=directory/shared/trunk/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/PoolableLdapConnectionFactory.java&r1=1636845&r2=1637004&rev=1637004&view=diff ============================================================================== --- directory/shared/trunk/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/PoolableLdapConnectionFactory.java (original) +++ directory/shared/trunk/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/ValidatingPoolableLdapConnectionFactory.java Wed Nov 5 23:17:10 2014 @@ -23,8 +23,6 @@ package org.apache.directory.ldap.client import java.io.IOException; -import org.apache.commons.pool.PoolableObjectFactory; -import org.apache.directory.api.ldap.codec.api.LdapApiService; import org.apache.directory.api.ldap.model.constants.SchemaConstants; import org.apache.directory.api.ldap.model.exception.LdapException; import org.apache.directory.api.ldap.model.name.Dn; @@ -33,15 +31,20 @@ import org.slf4j.LoggerFactory; /** - * A factory for creating LdapConnection objects managed by LdapConnectionPool. + * A factory for creating LdapConnection objects managed by LdapConnectionPool. The connections are validated + * before being returned, which leads to a round-trip to the server. It also re-bind the connection when + * it's being put back to the pool, to reset the LDAPSession. + * + * This is quite a costly - but secure - way to handle connections in a pool. If one would like to use a + * less expensive pool factory, the {@link DefaultPoolableLdapConnectionFactory} is most certainly a better + * choice. * * @author Apache Directory Project */ -public class PoolableLdapConnectionFactory implements PoolableObjectFactory +public class ValidatingPoolableLdapConnectionFactory extends AbstractPoolableLdapConnectionFactory { - private static final Logger LOG = LoggerFactory.getLogger( PoolableLdapConnectionFactory.class ); - - private LdapConnectionFactory connectionFactory; + /** This class logger */ + private static final Logger LOG = LoggerFactory.getLogger( ValidatingPoolableLdapConnectionFactory.class ); /** @@ -49,7 +52,7 @@ public class PoolableLdapConnectionFacto * * @param config the configuration for creating LdapConnections */ - public PoolableLdapConnectionFactory( LdapConnectionConfig config ) + public ValidatingPoolableLdapConnectionFactory( LdapConnectionConfig config ) { this( new DefaultLdapConnectionFactory( config ) ); } @@ -60,7 +63,7 @@ public class PoolableLdapConnectionFacto * * @param connectionFactory the connection factory for creating LdapConnections */ - public PoolableLdapConnectionFactory( LdapConnectionFactory connectionFactory ) + public ValidatingPoolableLdapConnectionFactory( LdapConnectionFactory connectionFactory ) { this.connectionFactory = connectionFactory; } @@ -68,6 +71,8 @@ public class PoolableLdapConnectionFacto /** * {@inheritDoc} + * + * There is nothing to do to activate a connection. */ public void activateObject( LdapConnection connection ) { @@ -77,10 +82,14 @@ public class PoolableLdapConnectionFacto /** * {@inheritDoc} + * + * Destroying a connection will unbind it which will result on a shutdown + * of teh underlying protocol. */ public void destroyObject( LdapConnection connection ) { LOG.debug( "Destroying {}", connection ); + if ( connection.isConnected() ) { try @@ -107,29 +116,26 @@ public class PoolableLdapConnectionFacto /** - * Returns the LdapApiService instance used by this factory. - * - * @return The LdapApiService instance used by this factory - */ - public LdapApiService getLdapApiService() - { - return connectionFactory.getLdapApiService(); - } - - - /** * {@inheritDoc} + * Specifically, we are creating a new connection based on the LdapConnection Factory + * we used to create this pool of connections. The default is to create bound connections. + * * @throws LdapException If unable to connect. */ public LdapConnection makeObject() throws LdapException { LOG.debug( "Creating a LDAP connection" ); + return connectionFactory.newLdapConnection(); } /** * {@inheritDoc} + * + * Here, passivating a connection means we re-bind it, so that the existing LDAPSession + * is reset. + * * @throws LdapException If unable to reconfigure and rebind. */ public void passivateObject( LdapConnection connection ) throws LdapException @@ -145,6 +151,10 @@ public class PoolableLdapConnectionFacto /** * {@inheritDoc} + * + * Validating a connection is done in depth : first we check that the connection is still + * up, that the LdapSession is authenticated, and that we can retrieve some information + * from the server. If the connection is not authenticated, we re-bind. */ public boolean validateObject( LdapConnection connection ) {