You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by yu...@apache.org on 2018/04/25 04:36:45 UTC

directory-fortress-core git commit: fixing buggy logic and implement HA at ldap connection provider

Repository: directory-fortress-core
Updated Branches:
  refs/heads/trivial/support-ha-client 5d7ed4a5b -> 621883ef6


fixing buggy logic and implement HA at ldap connection provider


Project: http://git-wip-us.apache.org/repos/asf/directory-fortress-core/repo
Commit: http://git-wip-us.apache.org/repos/asf/directory-fortress-core/commit/621883ef
Tree: http://git-wip-us.apache.org/repos/asf/directory-fortress-core/tree/621883ef
Diff: http://git-wip-us.apache.org/repos/asf/directory-fortress-core/diff/621883ef

Branch: refs/heads/trivial/support-ha-client
Commit: 621883ef64fa186b51855f3f390ceefc7ea13080
Parents: 5d7ed4a
Author: yudhi.k.surtan <yu...@gdn-commerce.com>
Authored: Wed Apr 25 11:36:33 2018 +0700
Committer: yudhi.k.surtan <yu...@gdn-commerce.com>
Committed: Wed Apr 25 11:36:33 2018 +0700

----------------------------------------------------------------------
 .../core/ldap/LdapConnectionProvider.java       | 206 +++++++++----------
 .../core/ldap/LdapHAConnectionPool.java         |  37 +++-
 2 files changed, 127 insertions(+), 116 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/621883ef/src/main/java/org/apache/directory/fortress/core/ldap/LdapConnectionProvider.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/ldap/LdapConnectionProvider.java b/src/main/java/org/apache/directory/fortress/core/ldap/LdapConnectionProvider.java
index 046c18b..4699576 100644
--- a/src/main/java/org/apache/directory/fortress/core/ldap/LdapConnectionProvider.java
+++ b/src/main/java/org/apache/directory/fortress/core/ldap/LdapConnectionProvider.java
@@ -58,6 +58,7 @@ import org.slf4j.LoggerFactory;
 public class LdapConnectionProvider
 {
 
+    private static final int DEFAULT_LDAP_TIMEOUT = 2000;
     private static final String CLS_NM = LdapConnectionProvider.class.getName();
     private static final Logger LOG = LoggerFactory.getLogger( CLS_NM );
 
@@ -72,17 +73,18 @@ public class LdapConnectionProvider
     /**
      * The Admin connection pool
      */
-    private static LdapConnectionPool adminPool;
+//    private static LdapConnectionPool adminPool;
+    private static LdapHAConnectionPool adminPool;
 
     /**
      * The Log connection pool
      */
-    private static LdapConnectionPool logPool;
+    private static LdapHAConnectionPool logPool;
 
     /**
      * The User connection pool
      */
-    private static LdapConnectionPool userPool;
+    private static LdapHAConnectionPool userPool;
 
     private static volatile LdapConnectionProvider sINSTANCE = null;
 
@@ -99,10 +101,12 @@ public class LdapConnectionProvider
             {
                 if ( sINSTANCE == null )
                 {
+                    LOG.info( "construct a new ldap connection provider" );
                     sINSTANCE = new LdapConnectionProvider();
                 }
             }
         }
+        LOG.info( "return existing ldap connection provider" );
         return sINSTANCE;
     }
 
@@ -133,81 +137,12 @@ public class LdapConnectionProvider
         int logmax = Config.getInstance().getInt( LDAP_LOG_POOL_MAX, 10 );
         LOG.info( "LDAP POOL:  host=[{}], port=[{}], min=[{}], max=[{}]", host, port, min, max );
 
-        LdapConnectionConfig config = new LdapConnectionConfig();
-        config.setLdapHost( host );
-        config.setLdapPort( port );
-        config.setName( Config.getInstance().getProperty( GlobalIds.LDAP_ADMIN_POOL_UID, "" ) );
-
-        config.setUseSsl( IS_SSL );
-        //config.setTrustManagers( new NoVerificationTrustManager() );
-
-        if ( Config.getInstance().getBoolean( ENABLE_LDAP_STARTTLS, false ) )
-        {
-            config.setUseTls( true );
-        }
-
-        if ( IS_SSL && StringUtils.isNotEmpty( Config.getInstance().getProperty( GlobalIds.TRUST_STORE ) ) &&
-            StringUtils.isNotEmpty( Config.getInstance().getProperty( GlobalIds.TRUST_STORE_PW ) ) )
-        {
-            // validate certificates but allow self-signed certs if within this truststore:
-            config.setTrustManagers( new LdapClientTrustStoreManager( Config.getInstance().getProperty( GlobalIds
-                .TRUST_STORE ), Config.getInstance().getProperty( GlobalIds.TRUST_STORE_PW ).toCharArray(), null,
-                true ) );
-        }
-
-        String adminPw;
-        if ( EncryptUtil.isEnabled() )
-        {
-            adminPw = EncryptUtil.getInstance().decrypt( Config.getInstance().getProperty( GlobalIds
-                .LDAP_ADMIN_POOL_PW, true ) );
-        }
-        else
-        {
-            adminPw = Config.getInstance().getProperty( GlobalIds.LDAP_ADMIN_POOL_PW, true );
-        }
-
-        config.setCredentials( adminPw );
-        try
-        {
-            List<String> listExOps = new ArrayList<>();
-            listExOps.add( "org.openldap.accelerator.impl.createSession.RbacCreateSessionFactory" );
-            listExOps.add( "org.openldap.accelerator.impl.checkAccess.RbacCheckAccessFactory" );
-            listExOps.add( "org.openldap.accelerator.impl.addRole.RbacAddRoleFactory" );
-            listExOps.add( "org.openldap.accelerator.impl.dropRole.RbacDropRoleFactory" );
-            listExOps.add( "org.openldap.accelerator.impl.deleteSession.RbacDeleteSessionFactory" );
-            listExOps.add( "org.openldap.accelerator.impl.sessionRoles.RbacSessionRolesFactory" );
-            LdapApiService ldapApiService = new StandaloneLdapApiService( new ArrayList<String>(), listExOps );
-
-            if ( !LdapApiServiceFactory.isInitialized() )
-            {
-                LdapApiServiceFactory.initialize( ldapApiService );
-            }
-            config.setLdapApiService( ldapApiService );
-        }
-        catch ( Exception ex )
-        {
-            String error = "Exception caught initializing Admin Pool: " + ex;
-            throw new CfgRuntimeException( GlobalErrIds.FT_APACHE_LDAP_POOL_INIT_FAILED, error, ex );
-        }
-
-        PoolableObjectFactory<LdapConnection> poolFactory = new ValidatingPoolableLdapConnectionFactory( config );
-
-        // Create the Admin pool
-        adminPool = new LdapConnectionPool( poolFactory );
-        adminPool.setTestOnBorrow( true );
-        adminPool.setWhenExhaustedAction( GenericObjectPool.WHEN_EXHAUSTED_GROW );
-        adminPool.setMaxActive( max );
-        adminPool.setMinIdle( min );
-        adminPool.setMaxIdle( -1 );
-        //adminPool.setMaxWait( 0 );
-
-        // Create the User pool
-        userPool = new LdapConnectionPool( poolFactory );
-        userPool.setTestOnBorrow( true );
-        userPool.setWhenExhaustedAction( GenericObjectPool.WHEN_EXHAUSTED_GROW );
-        userPool.setMaxActive( max );
-        userPool.setMinIdle( min );
-        userPool.setMaxIdle( -1 );
+        LdapConnectionConfig[] ldapConnectionConfigs = populateLdapConnectionConfigs( host, port, IS_SSL, Config.getInstance().getProperty( GlobalIds.LDAP_ADMIN_POOL_UID, "" ), Config.getInstance().getProperty( GlobalIds
+                .LDAP_ADMIN_POOL_PW, true ), Config.getInstance().getBoolean( ENABLE_LDAP_STARTTLS, false ), Config.getInstance().getProperty( GlobalIds
+                      .TRUST_STORE ), Config.getInstance().getProperty( GlobalIds.TRUST_STORE_PW ) );
+        
+        adminPool = new LdapHAConnectionPool( ldapConnectionConfigs, HAConnectionStrategy.ROUND_ROBIN, true, GenericObjectPool.WHEN_EXHAUSTED_GROW, max, min, -1, 2 );
+        userPool = new LdapHAConnectionPool( ldapConnectionConfigs, HAConnectionStrategy.ROUND_ROBIN, true, GenericObjectPool.WHEN_EXHAUSTED_GROW, max, min, -1, 2 );
 
         // This pool of access log connections is used by {@link org.apache.directory.fortress.AuditMgr}.
         // To enable, set {@code log.admin.user} && {@code log.admin.pw} inside fortress.properties file:
@@ -216,39 +151,13 @@ public class LdapConnectionProvider
             // Initializing the log pool in static block requires static props set within fortress.properties.
             // To make this dynamic requires moving this code outside of static block AND storing the connection
             // metadata inside fortress config node (in ldap).
-            LdapConnectionConfig logConfig = new LdapConnectionConfig();
-            logConfig.setLdapHost( host );
-            logConfig.setLdapPort( port );
-            logConfig.setName( Config.getInstance().getProperty( GlobalIds.LDAP_ADMIN_POOL_UID, "" ) );
-
-            logConfig.setUseSsl( IS_SSL );
-
-            if ( IS_SSL && StringUtils.isNotEmpty( Config.getInstance().getProperty( GlobalIds.TRUST_STORE ) ) &&
-                StringUtils.isNotEmpty( Config.getInstance().getProperty( GlobalIds.TRUST_STORE_PW, true ) ) )
-            {
-                // validate certificates but allow self-signed certs if within this truststore:
-                logConfig.setTrustManagers( new LdapClientTrustStoreManager( Config.getInstance().getProperty(
-                    GlobalIds.TRUST_STORE ), Config.getInstance().getProperty( GlobalIds.TRUST_STORE_PW, true ).toCharArray
-                    (), null, true ) );
-            }
-
-            logConfig.setName( Config.getInstance().getProperty( LDAP_LOG_POOL_UID, "" ) );
-            String logPw;
-            if ( EncryptUtil.isEnabled() )
-            {
-                logPw = EncryptUtil.getInstance().decrypt( Config.getInstance().getProperty( LDAP_LOG_POOL_PW, true ) );
-            }
-            else
-            {
-                logPw = Config.getInstance().getProperty( LDAP_LOG_POOL_PW, true );
-            }
-            logConfig.setCredentials( logPw );
-            poolFactory = new ValidatingPoolableLdapConnectionFactory( logConfig );
-            logPool = new LdapConnectionPool( poolFactory );
-            logPool.setTestOnBorrow( true );
-            logPool.setWhenExhaustedAction( GenericObjectPool.WHEN_EXHAUSTED_GROW );
-            logPool.setMaxActive( logmax );
-            logPool.setMinIdle( logmin );
+            LdapConnectionConfig logConfigs[] = populateLdapConnectionConfigs( host, port, IS_SSL, 
+                    Config.getInstance().getProperty( LDAP_LOG_POOL_UID, "" ), 
+                    Config.getInstance().getProperty( LDAP_LOG_POOL_PW, true ), 
+                    Config.getInstance().getBoolean( ENABLE_LDAP_STARTTLS, false ), Config.getInstance().getProperty( GlobalIds.TRUST_STORE ), Config.getInstance().getProperty( GlobalIds.TRUST_STORE_PW, true ) );
+            
+            
+            logPool = new LdapHAConnectionPool( logConfigs, HAConnectionStrategy.ROUND_ROBIN, true, GenericObjectPool.WHEN_EXHAUSTED_GROW, logmax, logmin, -1, 2 );
         }
     }
 
@@ -370,7 +279,7 @@ public class LdapConnectionProvider
     {
         try
         {
-            LOG.info( "Closing admin pool" );
+            LOG.trace( "Closing admin pool" );
             adminPool.close();
         }
         catch ( Exception e )
@@ -380,7 +289,7 @@ public class LdapConnectionProvider
 
         try
         {
-            LOG.info( "Closing user pool" );
+            LOG.trace( "Closing user pool" );
             userPool.close();
         }
         catch ( Exception e )
@@ -390,7 +299,7 @@ public class LdapConnectionProvider
 
         try
         {
-            LOG.info( "Closing log pool" );
+            LOG.trace( "Closing log pool" );
             logPool.close();
         }
         catch ( Exception e )
@@ -398,4 +307,73 @@ public class LdapConnectionProvider
             LOG.warn( "Error closing log pool: " + e.getMessage() );
         }
     }
+    
+    private LdapConnectionConfig[] populateLdapConnectionConfigs(String host, int port, boolean isSSL, String ldapAdminId, String ldapAdminPassword, boolean isEnableLdapStartTLS, String trustStore, String trustStorePassword) {
+        String[] hosts = null;
+        if(host.contains( "," )) {
+            hosts = host.split( "," );
+        } else {
+            hosts = new String[1];
+            hosts[0] = host;
+        }
+        LdapConnectionConfig[] configs = new LdapConnectionConfig[hosts.length];
+        for(int i = 0; i < hosts.length ; i++) {
+            configs[i] = new LdapConnectionConfig();
+            configs[i].setLdapHost( hosts[i] );
+            configs[i].setLdapPort( port );
+            configs[i].setName( ldapAdminId );
+            //TODO: later need to include at the configuration level to adjust the value.
+            configs[i].setTimeout( DEFAULT_LDAP_TIMEOUT );
+            configs[i].setUseSsl( isSSL );
+            //config.setTrustManagers( new NoVerificationTrustManager() );
+
+            if ( isEnableLdapStartTLS )
+            {
+                configs[i].setUseTls( true );
+            }
+
+            if ( isSSL && StringUtils.isNotEmpty( trustStore ) &&
+                StringUtils.isNotEmpty( trustStorePassword ) )
+            {
+                // validate certificates but allow self-signed certs if within this truststore:
+                configs[i].setTrustManagers( new LdapClientTrustStoreManager( trustStore, trustStorePassword.toCharArray(), null,
+                    true ) );
+            }
+
+            String adminPw;
+            if ( EncryptUtil.isEnabled() )
+            {
+                adminPw = EncryptUtil.getInstance().decrypt( ldapAdminPassword );
+            }
+            else
+            {
+                adminPw = ldapAdminPassword;
+            }
+
+            configs[i].setCredentials( adminPw );
+            try
+            {
+                List<String> listExOps = new ArrayList<>();
+                listExOps.add( "org.openldap.accelerator.impl.createSession.RbacCreateSessionFactory" );
+                listExOps.add( "org.openldap.accelerator.impl.checkAccess.RbacCheckAccessFactory" );
+                listExOps.add( "org.openldap.accelerator.impl.addRole.RbacAddRoleFactory" );
+                listExOps.add( "org.openldap.accelerator.impl.dropRole.RbacDropRoleFactory" );
+                listExOps.add( "org.openldap.accelerator.impl.deleteSession.RbacDeleteSessionFactory" );
+                listExOps.add( "org.openldap.accelerator.impl.sessionRoles.RbacSessionRolesFactory" );
+                LdapApiService ldapApiService = new StandaloneLdapApiService( new ArrayList<String>(), listExOps );
+
+                if ( !LdapApiServiceFactory.isInitialized() )
+                {
+                    LdapApiServiceFactory.initialize( ldapApiService );
+                }
+                configs[i].setLdapApiService( ldapApiService );
+            }
+            catch ( Exception ex )
+            {
+                String error = "Exception caught initializing Admin Pool: " + ex;
+                throw new CfgRuntimeException( GlobalErrIds.FT_APACHE_LDAP_POOL_INIT_FAILED, error, ex );
+            }
+        }
+        return configs;
+    }
 }

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/621883ef/src/main/java/org/apache/directory/fortress/core/ldap/LdapHAConnectionPool.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/ldap/LdapHAConnectionPool.java b/src/main/java/org/apache/directory/fortress/core/ldap/LdapHAConnectionPool.java
index 238c399..5eaa5b0 100644
--- a/src/main/java/org/apache/directory/fortress/core/ldap/LdapHAConnectionPool.java
+++ b/src/main/java/org/apache/directory/fortress/core/ldap/LdapHAConnectionPool.java
@@ -1,7 +1,10 @@
 package org.apache.directory.fortress.core.ldap;
 
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
+import java.util.UUID;
 import java.util.concurrent.atomic.AtomicInteger;
 
 import org.apache.commons.pool.impl.GenericObjectPool;
@@ -44,16 +47,36 @@ public class LdapHAConnectionPool
         connectionPools = new LdapConnectionPool[configs.length];
         for ( int i = 0; i < configs.length; i++ )
         {
-            connectionPools[i] = new LdapConnectionPool( new ValidatingPoolableLdapConnectionFactory( configs[i] ) );
+            ValidatingPoolableLdapConnectionFactory validatingPoolableLdapConnectionFactory = new ValidatingPoolableLdapConnectionFactory( configs[i] );
+            connectionPools[i] = new LdapConnectionPool( validatingPoolableLdapConnectionFactory );
             connectionPools[i].setTestOnBorrow( true );
             connectionPools[i].setWhenExhaustedAction( GenericObjectPool.WHEN_EXHAUSTED_GROW );
             connectionPools[i].setMaxActive( maxActive );
             connectionPools[i].setMinIdle( minIdle );
             connectionPools[i].setMaxIdle( maxIdle );
+            connectionPools[i].setTestWhileIdle( true );
         }
         this.connectionStrategy = connectionStrategy;
     }
 
+    public void close() throws Exception {
+        List<Exception> exceptions = new ArrayList<>();
+        String closingProcessId = UUID.randomUUID().toString().toUpperCase();
+        for(LdapConnectionPool connectionPool : connectionPools) {
+            try
+            {
+                connectionPool.close();
+            } catch ( Exception e )
+            {
+                LOG.error( "could not close connection pool, process id : " + closingProcessId, e );
+                exceptions.add( e );
+            }
+        }
+        if(!exceptions.isEmpty()) {
+            throw new Exception("there some close connection error, check your log for process id : " + closingProcessId);
+        }
+    }
+
     public LdapConnection getConnection() throws LdapException
     {
         LdapConnection connection;
@@ -82,6 +105,7 @@ public class LdapHAConnectionPool
                 try
                 {
                     int poolIndex = masterNodeIndex.get();
+                    LOG.trace( "active passive poolIndex : " + poolIndex );
                     borrowedConnection = connectionPools[poolIndex].borrowObject();
                     allowedRetriesCounter.set( allowedRetries );
                     CONNECTION_POOL_LOOKUP_TABLE.put( borrowedConnection.toString(), connectionPools[poolIndex] );
@@ -114,13 +138,16 @@ public class LdapHAConnectionPool
                 try
                 {
                     int poolIndex = getCurrentRequestNode();
+                    LOG.trace( "round robin poolIndex : " + poolIndex );
                     borrowedConnection = connectionPools[poolIndex].borrowObject();
                     allowedRetriesCounter.set( allowedRetries );
+                    LOG.trace( "putting " + borrowedConnection.toString() + " to the lookup pool" );
                     CONNECTION_POOL_LOOKUP_TABLE.put( borrowedConnection.toString(), connectionPools[poolIndex] );
                 } catch ( LdapException | RuntimeException e )
                 {
                     if ( allowedRetriesCounter.decrementAndGet() > 0 )
                     {
+                        LOG.trace( "retrying connection left " +  allowedRetriesCounter.get());
                         return getConnectionByStrategy();
                     } else
                     {
@@ -140,7 +167,13 @@ public class LdapHAConnectionPool
 
     private int getCurrentRequestNode()
     {
-        return requestCounter.getAndIncrement() % availableNodes;
+        int current = requestCounter.getAndIncrement();
+        LOG.trace( "current : "+ current );
+        if(Integer.MAX_VALUE == current) {
+            requestCounter.set( 0 );
+            current = 0;
+        }
+        return current % availableNodes;
     }
 
     public void releaseConnection( LdapConnection connection )