You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@manifoldcf.apache.org by kw...@apache.org on 2013/12/08 19:54:11 UTC

svn commit: r1549105 [1/2] - in /manifoldcf/trunk: ./ connectors/activedirectory/connector/src/main/java/org/apache/manifoldcf/authorities/authorities/activedirectory/ connectors/alfresco/connector/src/main/java/org/apache/manifoldcf/crawler/connectors...

Author: kwright
Date: Sun Dec  8 18:54:09 2013
New Revision: 1549105

URL: http://svn.apache.org/r1549105
Log:
More work for CONNECTORS-781.  This commit adds distributed connection pooling.

Added:
    manifoldcf/trunk/framework/core/src/main/java/org/apache/manifoldcf/core/interfaces/IServiceDataAcceptor.java
      - copied unchanged from r1549104, manifoldcf/branches/CONNECTORS-781/framework/core/src/main/java/org/apache/manifoldcf/core/interfaces/IServiceDataAcceptor.java
Modified:
    manifoldcf/trunk/   (props changed)
    manifoldcf/trunk/connectors/activedirectory/connector/src/main/java/org/apache/manifoldcf/authorities/authorities/activedirectory/ActiveDirectoryAuthority.java
    manifoldcf/trunk/connectors/alfresco/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/alfresco/AlfrescoRepositoryConnector.java
    manifoldcf/trunk/connectors/cmis/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/cmis/CmisRepositoryConnector.java
    manifoldcf/trunk/connectors/documentum/connector/src/main/java/org/apache/manifoldcf/crawler/authorities/DCTM/AuthorityConnector.java
    manifoldcf/trunk/connectors/documentum/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/DCTM/DCTM.java
    manifoldcf/trunk/connectors/dropbox/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/dropbox/DropboxRepositoryConnector.java
    manifoldcf/trunk/connectors/elasticsearch/connector/src/main/java/org/apache/manifoldcf/agents/output/elasticsearch/ElasticSearchConnector.java
    manifoldcf/trunk/connectors/filenet/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/filenet/FilenetConnector.java
    manifoldcf/trunk/connectors/generic/connector/src/main/java/org/apache/manifoldcf/authorities/authorities/generic/GenericAuthority.java
    manifoldcf/trunk/connectors/googledrive/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/googledrive/GoogleDriveRepositoryConnector.java
    manifoldcf/trunk/connectors/hdfs/connector/src/main/java/org/apache/manifoldcf/agents/output/hdfs/HDFSOutputConnector.java
    manifoldcf/trunk/connectors/hdfs/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/hdfs/HDFSRepositoryConnector.java
    manifoldcf/trunk/connectors/jira/connector/src/main/java/org/apache/manifoldcf/authorities/authorities/jira/JiraAuthorityConnector.java
    manifoldcf/trunk/connectors/jira/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/jira/JiraRepositoryConnector.java
    manifoldcf/trunk/connectors/ldap/connector/src/main/java/org/apache/manifoldcf/authorities/authorities/ldap/LDAPAuthority.java
    manifoldcf/trunk/connectors/livelink/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/livelink/LivelinkAuthority.java
    manifoldcf/trunk/connectors/livelink/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/livelink/LivelinkConnector.java
    manifoldcf/trunk/connectors/opensearchserver/connector/src/main/java/org/apache/manifoldcf/agents/output/opensearchserver/OpenSearchServerConnector.java
    manifoldcf/trunk/connectors/sharepoint/   (props changed)
    manifoldcf/trunk/connectors/sharepoint/connector/src/main/java/org/apache/manifoldcf/authorities/authorities/sharepoint/SharePointADAuthority.java
    manifoldcf/trunk/connectors/sharepoint/connector/src/main/java/org/apache/manifoldcf/authorities/authorities/sharepoint/SharePointAuthority.java
    manifoldcf/trunk/connectors/sharepoint/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/sharepoint/SharePointRepository.java
    manifoldcf/trunk/connectors/solr/connector/src/main/java/org/apache/manifoldcf/agents/output/solr/SolrConnector.java
    manifoldcf/trunk/framework/agents/src/main/java/org/apache/manifoldcf/agents/incrementalingest/IncrementalIngester.java
    manifoldcf/trunk/framework/agents/src/main/java/org/apache/manifoldcf/agents/interfaces/IOutputConnectorPool.java
    manifoldcf/trunk/framework/agents/src/main/java/org/apache/manifoldcf/agents/outputconnectorpool/OutputConnectorPool.java
    manifoldcf/trunk/framework/agents/src/main/java/org/apache/manifoldcf/agents/system/IdleCleanupThread.java
    manifoldcf/trunk/framework/core/src/main/java/org/apache/manifoldcf/core/connector/BaseConnector.java
    manifoldcf/trunk/framework/core/src/main/java/org/apache/manifoldcf/core/connectorpool/ConnectorPool.java
    manifoldcf/trunk/framework/core/src/main/java/org/apache/manifoldcf/core/database/DBInterfaceHSQLDB.java
    manifoldcf/trunk/framework/core/src/main/java/org/apache/manifoldcf/core/interfaces/IConnector.java
    manifoldcf/trunk/framework/core/src/main/java/org/apache/manifoldcf/core/interfaces/ILockManager.java
    manifoldcf/trunk/framework/core/src/main/java/org/apache/manifoldcf/core/jdbcpool/ConnectionPoolManager.java
    manifoldcf/trunk/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/BaseLockManager.java
    manifoldcf/trunk/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/LockManager.java
    manifoldcf/trunk/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/ZooKeeperConnection.java
    manifoldcf/trunk/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/ZooKeeperLockManager.java
    manifoldcf/trunk/framework/crawler-ui/src/main/webapp/editjob.jsp
    manifoldcf/trunk/framework/crawler-ui/src/main/webapp/execute.jsp
    manifoldcf/trunk/framework/crawler-ui/src/main/webapp/viewauthority.jsp
    manifoldcf/trunk/framework/crawler-ui/src/main/webapp/viewconnection.jsp
    manifoldcf/trunk/framework/crawler-ui/src/main/webapp/viewjob.jsp
    manifoldcf/trunk/framework/crawler-ui/src/main/webapp/viewmapper.jsp
    manifoldcf/trunk/framework/crawler-ui/src/main/webapp/viewoutput.jsp
    manifoldcf/trunk/framework/pull-agent/src/main/java/org/apache/manifoldcf/authorities/CheckAll.java
    manifoldcf/trunk/framework/pull-agent/src/main/java/org/apache/manifoldcf/authorities/authorityconnectorpool/AuthorityConnectorPool.java
    manifoldcf/trunk/framework/pull-agent/src/main/java/org/apache/manifoldcf/authorities/interfaces/IAuthorityConnectorPool.java
    manifoldcf/trunk/framework/pull-agent/src/main/java/org/apache/manifoldcf/authorities/interfaces/IMappingConnectorPool.java
    manifoldcf/trunk/framework/pull-agent/src/main/java/org/apache/manifoldcf/authorities/mappingconnectorpool/MappingConnectorPool.java
    manifoldcf/trunk/framework/pull-agent/src/main/java/org/apache/manifoldcf/authorities/system/AuthCheckThread.java
    manifoldcf/trunk/framework/pull-agent/src/main/java/org/apache/manifoldcf/authorities/system/IdleCleanupThread.java
    manifoldcf/trunk/framework/pull-agent/src/main/java/org/apache/manifoldcf/authorities/system/MappingThread.java
    manifoldcf/trunk/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/interfaces/IRepositoryConnectorPool.java
    manifoldcf/trunk/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/jobs/JobManager.java
    manifoldcf/trunk/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/repositoryconnectorpool/RepositoryConnectorPool.java
    manifoldcf/trunk/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/system/DocumentCleanupThread.java
    manifoldcf/trunk/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/system/ExpireThread.java
    manifoldcf/trunk/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/system/IdleCleanupThread.java
    manifoldcf/trunk/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/system/JobNotificationThread.java
    manifoldcf/trunk/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/system/ManifoldCF.java
    manifoldcf/trunk/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/system/SeedingThread.java
    manifoldcf/trunk/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/system/StartupThread.java
    manifoldcf/trunk/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/system/StufferThread.java
    manifoldcf/trunk/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/system/WorkerThread.java

Propchange: manifoldcf/trunk/
------------------------------------------------------------------------------
  Merged /manifoldcf/branches/CONNECTORS-781:r1548085-1549104

Modified: manifoldcf/trunk/connectors/activedirectory/connector/src/main/java/org/apache/manifoldcf/authorities/authorities/activedirectory/ActiveDirectoryAuthority.java
URL: http://svn.apache.org/viewvc/manifoldcf/trunk/connectors/activedirectory/connector/src/main/java/org/apache/manifoldcf/authorities/authorities/activedirectory/ActiveDirectoryAuthority.java?rev=1549105&r1=1549104&r2=1549105&view=diff
==============================================================================
--- manifoldcf/trunk/connectors/activedirectory/connector/src/main/java/org/apache/manifoldcf/authorities/authorities/activedirectory/ActiveDirectoryAuthority.java (original)
+++ manifoldcf/trunk/connectors/activedirectory/connector/src/main/java/org/apache/manifoldcf/authorities/authorities/activedirectory/ActiveDirectoryAuthority.java Sun Dec  8 18:54:09 2013
@@ -214,7 +214,21 @@ public class ActiveDirectoryAuthority ex
     super.poll();
   }
   
-  
+  /** This method is called to assess whether to count this connector instance should
+  * actually be counted as being connected.
+  *@return true if the connector instance is actually connected.
+  */
+  @Override
+  public boolean isConnected()
+  {
+    for (Map.Entry<String,DCSessionInfo> sessionEntry : sessionInfo.entrySet())
+    {
+      if (sessionEntry.getValue().isOpen())
+        return true;
+    }
+    return false;
+  }
+
   /** Close the connection.  Call this before discarding the repository connector.
   */
   @Override
@@ -917,6 +931,11 @@ public class ActiveDirectoryAuthority ex
         closeConnection();
     }
 
+    /** Check if open */
+    protected boolean isOpen()
+    {
+      return ctx != null;
+    }
   }
 
   /** Class describing a domain suffix and corresponding domain controller name rule.

Modified: manifoldcf/trunk/connectors/alfresco/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/alfresco/AlfrescoRepositoryConnector.java
URL: http://svn.apache.org/viewvc/manifoldcf/trunk/connectors/alfresco/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/alfresco/AlfrescoRepositoryConnector.java?rev=1549105&r1=1549104&r2=1549105&view=diff
==============================================================================
--- manifoldcf/trunk/connectors/alfresco/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/alfresco/AlfrescoRepositoryConnector.java (original)
+++ manifoldcf/trunk/connectors/alfresco/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/alfresco/AlfrescoRepositoryConnector.java Sun Dec  8 18:54:09 2013
@@ -377,6 +377,16 @@ public class AlfrescoRepositoryConnector
     }
   }
 
+  /** This method is called to assess whether to count this connector instance should
+  * actually be counted as being connected.
+  *@return true if the connector instance is actually connected.
+  */
+  @Override
+  public boolean isConnected()
+  {
+    return session != null;
+  }
+
   /** Queue "seed" documents.  Seed documents are the starting places for crawling activity.  Documents
    * are seeded when this method calls appropriate methods in the passed in ISeedingActivity object.
    *

Modified: manifoldcf/trunk/connectors/cmis/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/cmis/CmisRepositoryConnector.java
URL: http://svn.apache.org/viewvc/manifoldcf/trunk/connectors/cmis/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/cmis/CmisRepositoryConnector.java?rev=1549105&r1=1549104&r2=1549105&view=diff
==============================================================================
--- manifoldcf/trunk/connectors/cmis/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/cmis/CmisRepositoryConnector.java (original)
+++ manifoldcf/trunk/connectors/cmis/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/cmis/CmisRepositoryConnector.java Sun Dec  8 18:54:09 2013
@@ -603,6 +603,16 @@ public class CmisRepositoryConnector ext
     }
   }
 
+  /** This method is called to assess whether to count this connector instance should
+  * actually be counted as being connected.
+  *@return true if the connector instance is actually connected.
+  */
+  @Override
+  public boolean isConnected()
+  {
+    return session != null;
+  }
+
   /** Queue "seed" documents.  Seed documents are the starting places for crawling activity.  Documents
    * are seeded when this method calls appropriate methods in the passed in ISeedingActivity object.
    *

Modified: manifoldcf/trunk/connectors/documentum/connector/src/main/java/org/apache/manifoldcf/crawler/authorities/DCTM/AuthorityConnector.java
URL: http://svn.apache.org/viewvc/manifoldcf/trunk/connectors/documentum/connector/src/main/java/org/apache/manifoldcf/crawler/authorities/DCTM/AuthorityConnector.java?rev=1549105&r1=1549104&r2=1549105&view=diff
==============================================================================
--- manifoldcf/trunk/connectors/documentum/connector/src/main/java/org/apache/manifoldcf/crawler/authorities/DCTM/AuthorityConnector.java (original)
+++ manifoldcf/trunk/connectors/documentum/connector/src/main/java/org/apache/manifoldcf/crawler/authorities/DCTM/AuthorityConnector.java Sun Dec  8 18:54:09 2013
@@ -947,6 +947,16 @@ public class AuthorityConnector extends 
 
   }
 
+  /** This method is called to assess whether to count this connector instance should
+  * actually be counted as being connected.
+  *@return true if the connector instance is actually connected.
+  */
+  @Override
+  public boolean isConnected()
+  {
+    return session != null;
+  }
+
   /** Disconnect from Documentum.
   */
   @Override

Modified: manifoldcf/trunk/connectors/documentum/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/DCTM/DCTM.java
URL: http://svn.apache.org/viewvc/manifoldcf/trunk/connectors/documentum/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/DCTM/DCTM.java?rev=1549105&r1=1549104&r2=1549105&view=diff
==============================================================================
--- manifoldcf/trunk/connectors/documentum/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/DCTM/DCTM.java (original)
+++ manifoldcf/trunk/connectors/documentum/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/DCTM/DCTM.java Sun Dec  8 18:54:09 2013
@@ -653,6 +653,16 @@ public class DCTM extends org.apache.man
     releaseCheck();
   }
 
+  /** This method is called to assess whether to count this connector instance should
+  * actually be counted as being connected.
+  *@return true if the connector instance is actually connected.
+  */
+  @Override
+  public boolean isConnected()
+  {
+    return session != null;
+  }
+
   /** Disconnect from Documentum.
   */
   @Override

Modified: manifoldcf/trunk/connectors/dropbox/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/dropbox/DropboxRepositoryConnector.java
URL: http://svn.apache.org/viewvc/manifoldcf/trunk/connectors/dropbox/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/dropbox/DropboxRepositoryConnector.java?rev=1549105&r1=1549104&r2=1549105&view=diff
==============================================================================
--- manifoldcf/trunk/connectors/dropbox/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/dropbox/DropboxRepositoryConnector.java (original)
+++ manifoldcf/trunk/connectors/dropbox/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/dropbox/DropboxRepositoryConnector.java Sun Dec  8 18:54:09 2013
@@ -320,6 +320,16 @@ public class DropboxRepositoryConnector 
 
   }
 
+  /** This method is called to assess whether to count this connector instance should
+  * actually be counted as being connected.
+  *@return true if the connector instance is actually connected.
+  */
+  @Override
+  public boolean isConnected()
+  {
+    return session != null;
+  }
+
   /**
    * Get the maximum number of documents to amalgamate together into one
    * batch, for this connector.

Modified: manifoldcf/trunk/connectors/elasticsearch/connector/src/main/java/org/apache/manifoldcf/agents/output/elasticsearch/ElasticSearchConnector.java
URL: http://svn.apache.org/viewvc/manifoldcf/trunk/connectors/elasticsearch/connector/src/main/java/org/apache/manifoldcf/agents/output/elasticsearch/ElasticSearchConnector.java?rev=1549105&r1=1549104&r2=1549105&view=diff
==============================================================================
--- manifoldcf/trunk/connectors/elasticsearch/connector/src/main/java/org/apache/manifoldcf/agents/output/elasticsearch/ElasticSearchConnector.java (original)
+++ manifoldcf/trunk/connectors/elasticsearch/connector/src/main/java/org/apache/manifoldcf/agents/output/elasticsearch/ElasticSearchConnector.java Sun Dec  8 18:54:09 2013
@@ -168,6 +168,16 @@ public class ElasticSearchConnector exte
     expirationTime = -1L;
   }
   
+  /** This method is called to assess whether to count this connector instance should
+  * actually be counted as being connected.
+  *@return true if the connector instance is actually connected.
+  */
+  @Override
+  public boolean isConnected()
+  {
+    return connectionManager != null;
+  }
+
   @Override
   public void disconnect()
     throws ManifoldCFException

Modified: manifoldcf/trunk/connectors/filenet/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/filenet/FilenetConnector.java
URL: http://svn.apache.org/viewvc/manifoldcf/trunk/connectors/filenet/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/filenet/FilenetConnector.java?rev=1549105&r1=1549104&r2=1549105&view=diff
==============================================================================
--- manifoldcf/trunk/connectors/filenet/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/filenet/FilenetConnector.java (original)
+++ manifoldcf/trunk/connectors/filenet/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/filenet/FilenetConnector.java Sun Dec  8 18:54:09 2013
@@ -473,6 +473,16 @@ public class FilenetConnector extends or
     releaseCheck();
   }
 
+  /** This method is called to assess whether to count this connector instance should
+  * actually be counted as being connected.
+  *@return true if the connector instance is actually connected.
+  */
+  @Override
+  public boolean isConnected()
+  {
+    return session != null;
+  }
+
   /** Disconnect from Filenet.
   */
   @Override

Modified: manifoldcf/trunk/connectors/generic/connector/src/main/java/org/apache/manifoldcf/authorities/authorities/generic/GenericAuthority.java
URL: http://svn.apache.org/viewvc/manifoldcf/trunk/connectors/generic/connector/src/main/java/org/apache/manifoldcf/authorities/authorities/generic/GenericAuthority.java?rev=1549105&r1=1549104&r2=1549105&view=diff
==============================================================================
--- manifoldcf/trunk/connectors/generic/connector/src/main/java/org/apache/manifoldcf/authorities/authorities/generic/GenericAuthority.java (original)
+++ manifoldcf/trunk/connectors/generic/connector/src/main/java/org/apache/manifoldcf/authorities/authorities/generic/GenericAuthority.java Sun Dec  8 18:54:09 2013
@@ -188,6 +188,16 @@ public class GenericAuthority extends or
     super.poll();
   }
 
+  /** This method is called to assess whether to count this connector instance should
+  * actually be counted as being connected.
+  *@return true if the connector instance is actually connected.
+  */
+  @Override
+  public boolean isConnected()
+  {
+    return client != null;
+  }
+
   /**
    * Check connection for sanity.
    */

Modified: manifoldcf/trunk/connectors/googledrive/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/googledrive/GoogleDriveRepositoryConnector.java
URL: http://svn.apache.org/viewvc/manifoldcf/trunk/connectors/googledrive/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/googledrive/GoogleDriveRepositoryConnector.java?rev=1549105&r1=1549104&r2=1549105&view=diff
==============================================================================
--- manifoldcf/trunk/connectors/googledrive/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/googledrive/GoogleDriveRepositoryConnector.java (original)
+++ manifoldcf/trunk/connectors/googledrive/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/googledrive/GoogleDriveRepositoryConnector.java Sun Dec  8 18:54:09 2013
@@ -384,6 +384,16 @@ public class GoogleDriveRepositoryConnec
     }
   }
 
+  /** This method is called to assess whether to count this connector instance should
+  * actually be counted as being connected.
+  *@return true if the connector instance is actually connected.
+  */
+  @Override
+  public boolean isConnected()
+  {
+    return session != null;
+  }
+
   /**
    * Get the maximum number of documents to amalgamate together into one
    * batch, for this connector.

Modified: manifoldcf/trunk/connectors/hdfs/connector/src/main/java/org/apache/manifoldcf/agents/output/hdfs/HDFSOutputConnector.java
URL: http://svn.apache.org/viewvc/manifoldcf/trunk/connectors/hdfs/connector/src/main/java/org/apache/manifoldcf/agents/output/hdfs/HDFSOutputConnector.java?rev=1549105&r1=1549104&r2=1549105&view=diff
==============================================================================
--- manifoldcf/trunk/connectors/hdfs/connector/src/main/java/org/apache/manifoldcf/agents/output/hdfs/HDFSOutputConnector.java (original)
+++ manifoldcf/trunk/connectors/hdfs/connector/src/main/java/org/apache/manifoldcf/agents/output/hdfs/HDFSOutputConnector.java Sun Dec  8 18:54:09 2013
@@ -118,6 +118,16 @@ public class HDFSOutputConnector extends
     user = configParams.getParameter(ParameterEnum.user.name());
   }
 
+  /** This method is called to assess whether to count this connector instance should
+  * actually be counted as being connected.
+  *@return true if the connector instance is actually connected.
+  */
+  @Override
+  public boolean isConnected()
+  {
+    return session != null;
+  }
+
   /** Close the connection.  Call this before discarding the connection.
    */
   @Override

Modified: manifoldcf/trunk/connectors/hdfs/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/hdfs/HDFSRepositoryConnector.java
URL: http://svn.apache.org/viewvc/manifoldcf/trunk/connectors/hdfs/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/hdfs/HDFSRepositoryConnector.java?rev=1549105&r1=1549104&r2=1549105&view=diff
==============================================================================
--- manifoldcf/trunk/connectors/hdfs/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/hdfs/HDFSRepositoryConnector.java (original)
+++ manifoldcf/trunk/connectors/hdfs/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/hdfs/HDFSRepositoryConnector.java Sun Dec  8 18:54:09 2013
@@ -220,6 +220,16 @@ public class HDFSRepositoryConnector ext
     }
   }
 
+  /** This method is called to assess whether to count this connector instance should
+  * actually be counted as being connected.
+  *@return true if the connector instance is actually connected.
+  */
+  @Override
+  public boolean isConnected()
+  {
+    return session != null;
+  }
+
   /**
    * @throws ManifoldCFException
    */

Modified: manifoldcf/trunk/connectors/jira/connector/src/main/java/org/apache/manifoldcf/authorities/authorities/jira/JiraAuthorityConnector.java
URL: http://svn.apache.org/viewvc/manifoldcf/trunk/connectors/jira/connector/src/main/java/org/apache/manifoldcf/authorities/authorities/jira/JiraAuthorityConnector.java?rev=1549105&r1=1549104&r2=1549105&view=diff
==============================================================================
--- manifoldcf/trunk/connectors/jira/connector/src/main/java/org/apache/manifoldcf/authorities/authorities/jira/JiraAuthorityConnector.java (original)
+++ manifoldcf/trunk/connectors/jira/connector/src/main/java/org/apache/manifoldcf/authorities/authorities/jira/JiraAuthorityConnector.java Sun Dec  8 18:54:09 2013
@@ -223,6 +223,16 @@ public class JiraAuthorityConnector exte
     return session;
   }
 
+  /** This method is called to assess whether to count this connector instance should
+  * actually be counted as being connected.
+  *@return true if the connector instance is actually connected.
+  */
+  @Override
+  public boolean isConnected()
+  {
+    return session != null;
+  }
+
   @Override
   public void poll() throws ManifoldCFException {
     if (lastSessionFetch == -1L) {

Modified: manifoldcf/trunk/connectors/jira/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/jira/JiraRepositoryConnector.java
URL: http://svn.apache.org/viewvc/manifoldcf/trunk/connectors/jira/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/jira/JiraRepositoryConnector.java?rev=1549105&r1=1549104&r2=1549105&view=diff
==============================================================================
--- manifoldcf/trunk/connectors/jira/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/jira/JiraRepositoryConnector.java (original)
+++ manifoldcf/trunk/connectors/jira/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/jira/JiraRepositoryConnector.java Sun Dec  8 18:54:09 2013
@@ -298,6 +298,16 @@ public class JiraRepositoryConnector ext
     return session;
   }
 
+  /** This method is called to assess whether to count this connector instance should
+  * actually be counted as being connected.
+  *@return true if the connector instance is actually connected.
+  */
+  @Override
+  public boolean isConnected()
+  {
+    return session != null;
+  }
+
   @Override
   public void poll() throws ManifoldCFException {
     if (lastSessionFetch == -1L) {

Modified: manifoldcf/trunk/connectors/ldap/connector/src/main/java/org/apache/manifoldcf/authorities/authorities/ldap/LDAPAuthority.java
URL: http://svn.apache.org/viewvc/manifoldcf/trunk/connectors/ldap/connector/src/main/java/org/apache/manifoldcf/authorities/authorities/ldap/LDAPAuthority.java?rev=1549105&r1=1549104&r2=1549105&view=diff
==============================================================================
--- manifoldcf/trunk/connectors/ldap/connector/src/main/java/org/apache/manifoldcf/authorities/authorities/ldap/LDAPAuthority.java (original)
+++ manifoldcf/trunk/connectors/ldap/connector/src/main/java/org/apache/manifoldcf/authorities/authorities/ldap/LDAPAuthority.java Sun Dec  8 18:54:09 2013
@@ -224,6 +224,16 @@ public class LDAPAuthority extends org.a
     return super.check();
   }
 
+  /** This method is called to assess whether to count this connector instance should
+  * actually be counted as being connected.
+  *@return true if the connector instance is actually connected.
+  */
+  @Override
+  public boolean isConnected()
+  {
+    return session != null;
+  }
+
   /**
    * Poll. The connection should be closed if it has been idle for too long.
    */

Modified: manifoldcf/trunk/connectors/livelink/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/livelink/LivelinkAuthority.java
URL: http://svn.apache.org/viewvc/manifoldcf/trunk/connectors/livelink/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/livelink/LivelinkAuthority.java?rev=1549105&r1=1549104&r2=1549105&view=diff
==============================================================================
--- manifoldcf/trunk/connectors/livelink/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/livelink/LivelinkAuthority.java (original)
+++ manifoldcf/trunk/connectors/livelink/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/livelink/LivelinkAuthority.java Sun Dec  8 18:54:09 2013
@@ -317,6 +317,16 @@ public class LivelinkAuthority extends o
     }
   }
 
+  /** This method is called to assess whether to count this connector instance should
+  * actually be counted as being connected.
+  *@return true if the connector instance is actually connected.
+  */
+  @Override
+  public boolean isConnected()
+  {
+    return hasConnected;
+  }
+
   /** Close the connection.  Call this before discarding the repository connector.
   */
   @Override

Modified: manifoldcf/trunk/connectors/livelink/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/livelink/LivelinkConnector.java
URL: http://svn.apache.org/viewvc/manifoldcf/trunk/connectors/livelink/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/livelink/LivelinkConnector.java?rev=1549105&r1=1549104&r2=1549105&view=diff
==============================================================================
--- manifoldcf/trunk/connectors/livelink/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/livelink/LivelinkConnector.java (original)
+++ manifoldcf/trunk/connectors/livelink/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/livelink/LivelinkConnector.java Sun Dec  8 18:54:09 2013
@@ -704,6 +704,16 @@ public class LivelinkConnector extends o
       }
     }
   }
+  
+  /** This method is called to assess whether to count this connector instance should
+  * actually be counted as being connected.
+  *@return true if the connector instance is actually connected.
+  */
+  @Override
+  public boolean isConnected()
+  {
+    return hasConnected;
+  }
 
   /** Close the connection.  Call this before discarding the repository connector.
   */

Modified: manifoldcf/trunk/connectors/opensearchserver/connector/src/main/java/org/apache/manifoldcf/agents/output/opensearchserver/OpenSearchServerConnector.java
URL: http://svn.apache.org/viewvc/manifoldcf/trunk/connectors/opensearchserver/connector/src/main/java/org/apache/manifoldcf/agents/output/opensearchserver/OpenSearchServerConnector.java?rev=1549105&r1=1549104&r2=1549105&view=diff
==============================================================================
--- manifoldcf/trunk/connectors/opensearchserver/connector/src/main/java/org/apache/manifoldcf/agents/output/opensearchserver/OpenSearchServerConnector.java (original)
+++ manifoldcf/trunk/connectors/opensearchserver/connector/src/main/java/org/apache/manifoldcf/agents/output/opensearchserver/OpenSearchServerConnector.java Sun Dec  8 18:54:09 2013
@@ -199,6 +199,16 @@ public class OpenSearchServerConnector e
     }
   }
 
+  /** This method is called to assess whether to count this connector instance should
+  * actually be counted as being connected.
+  *@return true if the connector instance is actually connected.
+  */
+  @Override
+  public boolean isConnected()
+  {
+    return connectionManager != null;
+  }
+
   @Override
   public String[] getActivitiesList() {
     return OPENSEARCHSERVER_ACTIVITIES;

Propchange: manifoldcf/trunk/connectors/sharepoint/
------------------------------------------------------------------------------
  Merged /manifoldcf/branches/CONNECTORS-781/connectors/sharepoint:r1548085-1549104

Modified: manifoldcf/trunk/connectors/sharepoint/connector/src/main/java/org/apache/manifoldcf/authorities/authorities/sharepoint/SharePointADAuthority.java
URL: http://svn.apache.org/viewvc/manifoldcf/trunk/connectors/sharepoint/connector/src/main/java/org/apache/manifoldcf/authorities/authorities/sharepoint/SharePointADAuthority.java?rev=1549105&r1=1549104&r2=1549105&view=diff
==============================================================================
--- manifoldcf/trunk/connectors/sharepoint/connector/src/main/java/org/apache/manifoldcf/authorities/authorities/sharepoint/SharePointADAuthority.java (original)
+++ manifoldcf/trunk/connectors/sharepoint/connector/src/main/java/org/apache/manifoldcf/authorities/authorities/sharepoint/SharePointADAuthority.java Sun Dec  8 18:54:09 2013
@@ -220,6 +220,21 @@ public class SharePointADAuthority exten
     super.poll();
   }
   
+  /** This method is called to assess whether to count this connector instance should
+  * actually be counted as being connected.
+  *@return true if the connector instance is actually connected.
+  */
+  @Override
+  public boolean isConnected()
+  {
+    for (Map.Entry<String,DCSessionInfo> sessionEntry : sessionInfo.entrySet())
+    {
+      if (sessionEntry.getValue().isOpen())
+        return true;
+    }
+    return false;
+  }
+
   /** Close the connection.  Call this before discarding the repository connector.
   */
   @Override
@@ -942,6 +957,12 @@ public class SharePointADAuthority exten
         closeConnection();
     }
 
+    /** Check if open */
+    protected boolean isOpen()
+    {
+      return ctx != null;
+    }
+
   }
 
   /** Class describing a domain suffix and corresponding domain controller name rule.

Modified: manifoldcf/trunk/connectors/sharepoint/connector/src/main/java/org/apache/manifoldcf/authorities/authorities/sharepoint/SharePointAuthority.java
URL: http://svn.apache.org/viewvc/manifoldcf/trunk/connectors/sharepoint/connector/src/main/java/org/apache/manifoldcf/authorities/authorities/sharepoint/SharePointAuthority.java?rev=1549105&r1=1549104&r2=1549105&view=diff
==============================================================================
--- manifoldcf/trunk/connectors/sharepoint/connector/src/main/java/org/apache/manifoldcf/authorities/authorities/sharepoint/SharePointAuthority.java (original)
+++ manifoldcf/trunk/connectors/sharepoint/connector/src/main/java/org/apache/manifoldcf/authorities/authorities/sharepoint/SharePointAuthority.java Sun Dec  8 18:54:09 2013
@@ -243,7 +243,17 @@ public class SharePointAuthority extends
       connectionManager.closeIdleConnections(60000L,TimeUnit.MILLISECONDS);
     super.poll();
   }
-  
+
+  /** This method is called to assess whether to count this connector instance should
+  * actually be counted as being connected.
+  *@return true if the connector instance is actually connected.
+  */
+  @Override
+  public boolean isConnected()
+  {
+    return connectionManager != null;
+  }
+
   /** Close the connection.  Call this before discarding the repository connector.
   */
   @Override

Modified: manifoldcf/trunk/connectors/sharepoint/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/sharepoint/SharePointRepository.java
URL: http://svn.apache.org/viewvc/manifoldcf/trunk/connectors/sharepoint/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/sharepoint/SharePointRepository.java?rev=1549105&r1=1549104&r2=1549105&view=diff
==============================================================================
--- manifoldcf/trunk/connectors/sharepoint/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/sharepoint/SharePointRepository.java (original)
+++ manifoldcf/trunk/connectors/sharepoint/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/sharepoint/SharePointRepository.java Sun Dec  8 18:54:09 2013
@@ -423,6 +423,16 @@ public class SharePointRepository extend
       connectionManager.closeIdleConnections(60000L,TimeUnit.MILLISECONDS);
   }
 
+  /** This method is called to assess whether to count this connector instance should
+  * actually be counted as being connected.
+  *@return true if the connector instance is actually connected.
+  */
+  @Override
+  public boolean isConnected()
+  {
+    return connectionManager != null;
+  }
+
   /** Request arbitrary connector information.
   * This method is called directly from the API in order to allow API users to perform any one of several connector-specific
   * queries.

Modified: manifoldcf/trunk/connectors/solr/connector/src/main/java/org/apache/manifoldcf/agents/output/solr/SolrConnector.java
URL: http://svn.apache.org/viewvc/manifoldcf/trunk/connectors/solr/connector/src/main/java/org/apache/manifoldcf/agents/output/solr/SolrConnector.java?rev=1549105&r1=1549104&r2=1549105&view=diff
==============================================================================
--- manifoldcf/trunk/connectors/solr/connector/src/main/java/org/apache/manifoldcf/agents/output/solr/SolrConnector.java (original)
+++ manifoldcf/trunk/connectors/solr/connector/src/main/java/org/apache/manifoldcf/agents/output/solr/SolrConnector.java Sun Dec  8 18:54:09 2013
@@ -110,6 +110,16 @@ public class SolrConnector extends org.a
     }
   }
 
+  /** This method is called to assess whether to count this connector instance should
+  * actually be counted as being connected.
+  *@return true if the connector instance is actually connected.
+  */
+  @Override
+  public boolean isConnected()
+  {
+    return poster != null;
+  }
+
   /** Close the connection.  Call this before discarding the connection.
   */
   @Override

Modified: manifoldcf/trunk/framework/agents/src/main/java/org/apache/manifoldcf/agents/incrementalingest/IncrementalIngester.java
URL: http://svn.apache.org/viewvc/manifoldcf/trunk/framework/agents/src/main/java/org/apache/manifoldcf/agents/incrementalingest/IncrementalIngester.java?rev=1549105&r1=1549104&r2=1549105&view=diff
==============================================================================
--- manifoldcf/trunk/framework/agents/src/main/java/org/apache/manifoldcf/agents/incrementalingest/IncrementalIngester.java (original)
+++ manifoldcf/trunk/framework/agents/src/main/java/org/apache/manifoldcf/agents/incrementalingest/IncrementalIngester.java Sun Dec  8 18:54:09 2013
@@ -216,7 +216,7 @@ public class IncrementalIngester extends
     }
     finally
     {
-      outputConnectorPool.release(connector);
+      outputConnectorPool.release(connection,connector);
     }
   }
 
@@ -241,7 +241,7 @@ public class IncrementalIngester extends
     }
     finally
     {
-      outputConnectorPool.release(connector);
+      outputConnectorPool.release(connection,connector);
     }
   }
 
@@ -267,7 +267,7 @@ public class IncrementalIngester extends
     }
     finally
     {
-      outputConnectorPool.release(connector);
+      outputConnectorPool.release(connection,connector);
     }
   }
 
@@ -293,7 +293,7 @@ public class IncrementalIngester extends
     }
     finally
     {
-      outputConnectorPool.release(connector);
+      outputConnectorPool.release(connection,connector);
     }
   }
 
@@ -317,7 +317,7 @@ public class IncrementalIngester extends
     }
     finally
     {
-      outputConnectorPool.release(connector);
+      outputConnectorPool.release(connection,connector);
     }
 
   }
@@ -1662,7 +1662,7 @@ public class IncrementalIngester extends
     }
     finally
     {
-      outputConnectorPool.release(connector);
+      outputConnectorPool.release(connection,connector);
     }
   }
 
@@ -1681,7 +1681,7 @@ public class IncrementalIngester extends
     }
     finally
     {
-      outputConnectorPool.release(connector);
+      outputConnectorPool.release(connection,connector);
     }
   }
 

Modified: manifoldcf/trunk/framework/agents/src/main/java/org/apache/manifoldcf/agents/interfaces/IOutputConnectorPool.java
URL: http://svn.apache.org/viewvc/manifoldcf/trunk/framework/agents/src/main/java/org/apache/manifoldcf/agents/interfaces/IOutputConnectorPool.java?rev=1549105&r1=1549104&r2=1549105&view=diff
==============================================================================
--- manifoldcf/trunk/framework/agents/src/main/java/org/apache/manifoldcf/agents/interfaces/IOutputConnectorPool.java (original)
+++ manifoldcf/trunk/framework/agents/src/main/java/org/apache/manifoldcf/agents/interfaces/IOutputConnectorPool.java Sun Dec  8 18:54:09 2013
@@ -47,15 +47,17 @@ public interface IOutputConnectorPool
     throws ManifoldCFException;
 
   /** Release multiple output connectors.
+  *@param connections are the connections describing the instances to release.
   *@param connectors are the connector instances to release.
   */
-  public void releaseMultiple(IOutputConnector[] connectors)
+  public void releaseMultiple(IOutputConnection[] connections, IOutputConnector[] connectors)
     throws ManifoldCFException;
 
   /** Release an output connector.
+  *@param connection is the connection describing the instance to release.
   *@param connector is the connector to release.
   */
-  public void release(IOutputConnector connector)
+  public void release(IOutputConnection connection, IOutputConnector connector)
     throws ManifoldCFException;
 
   /** Idle notification for inactive output connector handles.

Modified: manifoldcf/trunk/framework/agents/src/main/java/org/apache/manifoldcf/agents/outputconnectorpool/OutputConnectorPool.java
URL: http://svn.apache.org/viewvc/manifoldcf/trunk/framework/agents/src/main/java/org/apache/manifoldcf/agents/outputconnectorpool/OutputConnectorPool.java?rev=1549105&r1=1549104&r2=1549105&view=diff
==============================================================================
--- manifoldcf/trunk/framework/agents/src/main/java/org/apache/manifoldcf/agents/outputconnectorpool/OutputConnectorPool.java (original)
+++ manifoldcf/trunk/framework/agents/src/main/java/org/apache/manifoldcf/agents/outputconnectorpool/OutputConnectorPool.java Sun Dec  8 18:54:09 2013
@@ -35,9 +35,6 @@ public class OutputConnectorPool impleme
   /** Local connector pool */
   protected final static LocalPool localPool = new LocalPool();
 
-  // This implementation is a place-holder for the real one, which will likely fold in the pooling code
-  // as we strip it out of OutputConnectorFactory.
-
   /** Thread context */
   protected final IThreadContext threadContext;
   
@@ -59,18 +56,20 @@ public class OutputConnectorPool impleme
   {
     // For now, use the OutputConnectorFactory method.  This will require us to extract info
     // from each output connection, however.
+    String[] connectionNames = new String[outputConnections.length];
     String[] classNames = new String[outputConnections.length];
     ConfigParams[] configInfos = new ConfigParams[outputConnections.length];
     int[] maxPoolSizes = new int[outputConnections.length];
     
     for (int i = 0; i < outputConnections.length; i++)
     {
+      connectionNames[i] = outputConnections[i].getName();
       classNames[i] = outputConnections[i].getClassName();
       configInfos[i] = outputConnections[i].getConfigParams();
       maxPoolSizes[i] = outputConnections[i].getMaxConnections();
     }
     return localPool.grabMultiple(threadContext,
-      orderingKeys, classNames, configInfos, maxPoolSizes);
+      orderingKeys, connectionNames, classNames, configInfos, maxPoolSizes);
   }
 
   /** Get an output connector.
@@ -81,28 +80,35 @@ public class OutputConnectorPool impleme
   public IOutputConnector grab(IOutputConnection outputConnection)
     throws ManifoldCFException
   {
-    return localPool.grab(threadContext, outputConnection.getClassName(),
+    return localPool.grab(threadContext, outputConnection.getName(), outputConnection.getClassName(),
       outputConnection.getConfigParams(), outputConnection.getMaxConnections());
   }
 
   /** Release multiple output connectors.
+  *@param connections are the connections describing the instances to release.
   *@param connectors are the connector instances to release.
   */
   @Override
-  public void releaseMultiple(IOutputConnector[] connectors)
+  public void releaseMultiple(IOutputConnection[] connections, IOutputConnector[] connectors)
     throws ManifoldCFException
   {
-    localPool.releaseMultiple(connectors);
+    String[] connectionNames = new String[connections.length];
+    for (int i = 0; i < connections.length; i++)
+    {
+      connectionNames[i] = connections[i].getName();
+    }
+    localPool.releaseMultiple(threadContext, connectionNames, connectors);
   }
 
   /** Release an output connector.
+  *@param connection is the connection describing the instance to release.
   *@param connector is the connector to release.
   */
   @Override
-  public void release(IOutputConnector connector)
+  public void release(IOutputConnection connection, IOutputConnector connector)
     throws ManifoldCFException
   {
-    localPool.release(connector);
+    localPool.release(threadContext,connection.getName(),connector);
   }
 
   /** Idle notification for inactive output connector handles.
@@ -140,6 +146,7 @@ public class OutputConnectorPool impleme
   {
     public LocalPool()
     {
+      super("_OUTPUTCONNECTORPOOL_");
     }
     
     @Override
@@ -150,10 +157,18 @@ public class OutputConnectorPool impleme
       return connectorManager.isInstalled(className);
     }
 
-    public IOutputConnector[] grabMultiple(IThreadContext tc, String[] orderingKeys, String[] classNames, ConfigParams[] configInfos, int[] maxPoolSizes)
+    @Override
+    protected boolean isConnectionNameValid(IThreadContext tc, String connectionName)
+      throws ManifoldCFException
+    {
+      IOutputConnectionManager connectionManager = OutputConnectionManagerFactory.make(tc);
+      return connectionManager.load(connectionName) != null;
+    }
+
+    public IOutputConnector[] grabMultiple(IThreadContext tc, String[] orderingKeys, String[] connectionNames, String[] classNames, ConfigParams[] configInfos, int[] maxPoolSizes)
       throws ManifoldCFException
     {
-      return grabMultiple(tc,IOutputConnector.class,orderingKeys,classNames,configInfos,maxPoolSizes);
+      return grabMultiple(tc,IOutputConnector.class,orderingKeys,connectionNames,classNames,configInfos,maxPoolSizes);
     }
 
   }

Modified: manifoldcf/trunk/framework/agents/src/main/java/org/apache/manifoldcf/agents/system/IdleCleanupThread.java
URL: http://svn.apache.org/viewvc/manifoldcf/trunk/framework/agents/src/main/java/org/apache/manifoldcf/agents/system/IdleCleanupThread.java?rev=1549105&r1=1549104&r2=1549105&view=diff
==============================================================================
--- manifoldcf/trunk/framework/agents/src/main/java/org/apache/manifoldcf/agents/system/IdleCleanupThread.java (original)
+++ manifoldcf/trunk/framework/agents/src/main/java/org/apache/manifoldcf/agents/system/IdleCleanupThread.java Sun Dec  8 18:54:09 2013
@@ -67,7 +67,7 @@ public class IdleCleanupThread extends T
           cacheManager.expireObjects(System.currentTimeMillis());
           
           // Sleep for the retry interval.
-          ManifoldCF.sleep(15000L);
+          ManifoldCF.sleep(5000L);
         }
         catch (ManifoldCFException e)
         {

Modified: manifoldcf/trunk/framework/core/src/main/java/org/apache/manifoldcf/core/connector/BaseConnector.java
URL: http://svn.apache.org/viewvc/manifoldcf/trunk/framework/core/src/main/java/org/apache/manifoldcf/core/connector/BaseConnector.java?rev=1549105&r1=1549104&r2=1549105&view=diff
==============================================================================
--- manifoldcf/trunk/framework/core/src/main/java/org/apache/manifoldcf/core/connector/BaseConnector.java (original)
+++ manifoldcf/trunk/framework/core/src/main/java/org/apache/manifoldcf/core/connector/BaseConnector.java Sun Dec  8 18:54:09 2013
@@ -39,6 +39,7 @@ public abstract class BaseConnector impl
   * It is called when the connector is registered.
   *@param threadContext is the current thread context.
   */
+  @Override
   public void install(IThreadContext threadContext)
     throws ManifoldCFException
   {
@@ -50,6 +51,7 @@ public abstract class BaseConnector impl
   * It is called when the connector is deregistered.
   *@param threadContext is the current thread context.
   */
+  @Override
   public void deinstall(IThreadContext threadContext)
     throws ManifoldCFException
   {
@@ -59,6 +61,7 @@ public abstract class BaseConnector impl
   /** Connect.  The configuration parameters are included.
   *@param configParams are the configuration parameters for this connection.
   */
+  @Override
   public void connect(ConfigParams configParams)
   {
     params = configParams;
@@ -70,6 +73,7 @@ public abstract class BaseConnector impl
   /** Test the connection.  Returns a string describing the connection integrity.
   *@return the connection's status as a displayable string.
   */
+  @Override
   public String check()
     throws ManifoldCFException
   {
@@ -80,14 +84,27 @@ public abstract class BaseConnector impl
   /** This method is periodically called for all connectors that are connected but not
   * in active use.
   */
+  @Override
   public void poll()
     throws ManifoldCFException
   {
     // Base version does nothing
   }
 
+  /** This method is called to assess whether to count this connector instance should
+  * actually be counted as being connected.
+  *@return true if the connector instance is actually connected.
+  */
+  @Override
+  public boolean isConnected()
+  {
+    // Consider it connected.
+    return true;
+  }
+
   /** Close the connection.  Call this before discarding the repository connector.
   */
+  @Override
   public void disconnect()
     throws ManifoldCFException
   {
@@ -97,6 +114,7 @@ public abstract class BaseConnector impl
   /** Clear out any state information specific to a given thread.
   * This method is called when this object is returned to the connection pool.
   */
+  @Override
   public void clearThreadContext()
   {
     currentContext = null;
@@ -105,6 +123,7 @@ public abstract class BaseConnector impl
   /** Attach to a new thread.
   *@param threadContext is the new thread context.
   */
+  @Override
   public void setThreadContext(IThreadContext threadContext)
     throws ManifoldCFException
   {
@@ -114,6 +133,7 @@ public abstract class BaseConnector impl
   /** Get configuration information.
   *@return the configuration information for this class.
   */
+  @Override
   public ConfigParams getConfiguration()
   {
     return params;
@@ -128,6 +148,7 @@ public abstract class BaseConnector impl
   *@param parameters are the configuration parameters, as they currently exist, for this connection being configured.
   *@param tabsArray is an array of tab names.  Add to this array any tab names that are specific to the connector.
   */
+  @Override
   public void outputConfigurationHeader(IThreadContext threadContext, IHTTPOutput out, Locale locale, ConfigParams parameters, List<String> tabsArray)
     throws ManifoldCFException, IOException
   {
@@ -169,6 +190,7 @@ public abstract class BaseConnector impl
   *@param parameters are the configuration parameters, as they currently exist, for this connection being configured.
   *@param tabName is the current tab name.
   */
+  @Override
   public void outputConfigurationBody(IThreadContext threadContext, IHTTPOutput out, Locale locale, ConfigParams parameters, String tabName)
     throws ManifoldCFException, IOException
   {
@@ -199,6 +221,7 @@ public abstract class BaseConnector impl
   *@param parameters are the configuration parameters, as they currently exist, for this connection being configured.
   *@return null if all is well, or a string error message if there is an error that should prevent saving of the connection (and cause a redirection to an error page).
   */
+  @Override
   public String processConfigurationPost(IThreadContext threadContext, IPostParameters variableContext, Locale locale, ConfigParams parameters)
     throws ManifoldCFException
   {
@@ -228,6 +251,7 @@ public abstract class BaseConnector impl
   *@param locale is the locale that the output should use.
   *@param parameters are the configuration parameters, as they currently exist, for this connection being configured.
   */
+  @Override
   public void viewConfiguration(IThreadContext threadContext, IHTTPOutput out, Locale locale, ConfigParams parameters)
     throws ManifoldCFException, IOException
   {

Modified: manifoldcf/trunk/framework/core/src/main/java/org/apache/manifoldcf/core/connectorpool/ConnectorPool.java
URL: http://svn.apache.org/viewvc/manifoldcf/trunk/framework/core/src/main/java/org/apache/manifoldcf/core/connectorpool/ConnectorPool.java?rev=1549105&r1=1549104&r2=1549105&view=diff
==============================================================================
--- manifoldcf/trunk/framework/core/src/main/java/org/apache/manifoldcf/core/connectorpool/ConnectorPool.java (original)
+++ manifoldcf/trunk/framework/core/src/main/java/org/apache/manifoldcf/core/connectorpool/ConnectorPool.java Sun Dec  8 18:54:09 2013
@@ -31,12 +31,37 @@ public abstract class ConnectorPool<T ex
 {
   public static final String _rcsid = "@(#)$Id$";
 
-  // Pool hash table.
-  // Keyed by PoolKey; value is Pool
-  protected final Map<PoolKey,Pool> poolHash = new HashMap<PoolKey,Pool>();
+  // How global connector allocation works:
+  // (1) There is a lock-manager "service" associated with this connector pool.  This allows us to clean
+  // up after local pools that have died without being released.  There's one anonymous service instance per local pool,
+  // and thus one service instance per JVM.
+  // (2) Each local pool knows how many connector instances of each type (keyed by connection name) there
+  // are.
+  // (3) Each local pool/connector instance type has a local authorization count.  This is the amount it's
+  // allowed to actually keep.  If the pool has more connectors of a type than the local authorization count permits,
+  // then every connector release operation will destroy the released connector until the local authorization count
+  // is met.
+  // (4) Each local pool/connector instance type needs a global variable describing how many CURRENT instances
+  // the local pool has allocated.  This is a transient value which should automatically go to zero if the service becomes inactive.
+  // The lock manager has primitives now that allow data to be set this way.  We will use the connection name as the
+  // "data type" name - only in the local pool will we pay any attention to config info and class name, and flush those handles
+  // that get returned that have the wrong info attached.
 
-  protected ConnectorPool()
+  /** Target calc lock prefix */
+  protected final static String targetCalcLockPrefix = "_POOLTARGET_";
+  
+  /** Service type prefix */
+  protected final String serviceTypePrefix;
+
+  /** Pool hash table. Keyed by connection name; value is Pool */
+  protected final Map<String,Pool> poolHash = new HashMap<String,Pool>();
+
+  /** Random number */
+  protected final static Random randomNumberGenerator = new Random();
+  
+  protected ConnectorPool(String serviceTypePrefix)
   {
+    this.serviceTypePrefix = serviceTypePrefix;
   }
 
   // Protected methods
@@ -46,6 +71,11 @@ public abstract class ConnectorPool<T ex
   protected abstract boolean isInstalled(IThreadContext tc, String className)
     throws ManifoldCFException;
   
+  /** Override this method to check if a connection name is still valid.
+  */
+  protected abstract boolean isConnectionNameValid(IThreadContext tc, String connectionName)
+    throws ManifoldCFException;
+  
   /** Get a connector instance.
   *@param className is the class name.
   *@return the instance.
@@ -128,7 +158,8 @@ public abstract class ConnectorPool<T ex
   * so that any connector exhaustion will not cause a deadlock.
   */
   public T[] grabMultiple(IThreadContext threadContext, Class<T> clazz,
-    String[] orderingKeys, String[] classNames, ConfigParams[] configInfos, int[] maxPoolSizes)
+    String[] orderingKeys, String[] connectionNames,
+    String[] classNames, ConfigParams[] configInfos, int[] maxPoolSizes)
     throws ManifoldCFException
   {
     T[] rval = (T[])Array.newInstance(clazz,classNames.length);
@@ -144,12 +175,13 @@ public abstract class ConnectorPool<T ex
     {
       String orderingKey = orderingKeys[i];
       int index = orderMap.get(orderingKey).intValue();
+      String connectionName = connectionNames[index];
       String className = classNames[index];
       ConfigParams cp = configInfos[index];
       int maxPoolSize = maxPoolSizes[index];
       try
       {
-        T connector = grab(threadContext,className,cp,maxPoolSize);
+        T connector = grab(threadContext,connectionName,className,cp,maxPoolSize);
         rval[index] = connector;
       }
       catch (Throwable e)
@@ -161,7 +193,7 @@ public abstract class ConnectorPool<T ex
           index = orderMap.get(orderingKey).intValue();
           try
           {
-            release(rval[index]);
+            release(threadContext,connectionName,rval[index]);
           }
           catch (ManifoldCFException e2)
           {
@@ -181,53 +213,65 @@ public abstract class ConnectorPool<T ex
   }
 
   /** Get a connector.
-  * The connector is specified by its class and its parameters.
+  * The connector is specified by its connection name, class, and parameters.  If the
+  * class and parameters corresponding to a connection name change, then this code
+  * will destroy any old connector instance that does not correspond, and create a new
+  * one using the new class and parameters.
   *@param threadContext is the current thread context.
+  *@param connectionName is the name of the connection.  This functions as a pool key.
   *@param className is the name of the class to get a connector for.
   *@param configInfo are the name/value pairs constituting configuration info
   * for this class.
   */
-  public T grab(IThreadContext threadContext,
+  public T grab(IThreadContext threadContext, String connectionName,
     String className, ConfigParams configInfo, int maxPoolSize)
     throws ManifoldCFException
   {
     // We want to get handles off the pool and use them.  But the
     // handles we fetch have to have the right config information.
 
-    // Use the classname and config info to build a pool key.  This
-    // key will be discarded if we actually have to save a key persistently,
-    // since we avoid copying the configInfo unnecessarily.
-    PoolKey pk = new PoolKey(className,configInfo);
-    Pool p;
-    synchronized (poolHash)
+    // Loop until we successfully get a connector.  This is necessary because the
+    // pool may vanish because it has been closed.
+    while (true)
     {
-      p = poolHash.get(pk);
-      if (p == null)
+      Pool p;
+      synchronized (poolHash)
       {
-        pk = new PoolKey(className,configInfo.duplicate());
-        p = new Pool(pk,maxPoolSize);
-        poolHash.put(pk,p);
+        p = poolHash.get(connectionName);
+        if (p == null)
+        {
+          p = new Pool(threadContext, maxPoolSize, connectionName);
+          poolHash.put(connectionName,p);
+          // Do an initial poll right away, so we don't have to wait 5 seconds to 
+          // get a connector instance unless they're already all in use.
+          p.pollAll(threadContext);
+        }
+        else
+        {
+          p.updateMaximumPoolSize(threadContext, maxPoolSize);
+        }
       }
-    }
 
-    T rval = p.getConnector(threadContext);
-
-    return rval;
+      T rval = p.getConnector(threadContext,className,configInfo);
+      if (rval != null)
+        return rval;
+    }
 
   }
 
   /** Release multiple output connectors.
   */
-  public void releaseMultiple(T[] connectors)
+  public void releaseMultiple(IThreadContext threadContext, String[] connectionNames, T[] connectors)
     throws ManifoldCFException
   {
     ManifoldCFException currentException = null;
     for (int i = 0; i < connectors.length; i++)
     {
+      String connectionName = connectionNames[i];
       T c = connectors[i];
       try
       {
-        release(c);
+        release(threadContext,connectionName,c);
       }
       catch (ManifoldCFException e)
       {
@@ -240,9 +284,10 @@ public abstract class ConnectorPool<T ex
   }
 
   /** Release an output connector.
+  *@param connectionName is the connection name.
   *@param connector is the connector to release.
   */
-  public void release(T connector)
+  public void release(IThreadContext threadContext, String connectionName, T connector)
     throws ManifoldCFException
   {
     // If the connector is null, skip the release, because we never really got the connector in the first place.
@@ -250,14 +295,13 @@ public abstract class ConnectorPool<T ex
       return;
 
     // Figure out which pool this goes on, and put it there
-    PoolKey pk = new PoolKey(connector.getClass().getName(),connector.getConfiguration());
     Pool p;
     synchronized (poolHash)
     {
-      p = poolHash.get(pk);
+      p = poolHash.get(connectionName);
     }
 
-    p.releaseConnector(connector);
+    p.releaseConnector(threadContext, connector);
   }
 
   /** Idle notification for inactive output connector handles.
@@ -271,11 +315,18 @@ public abstract class ConnectorPool<T ex
     // Go through the whole pool and notify everyone
     synchronized (poolHash)
     {
-      Iterator<Pool> iter = poolHash.values().iterator();
+      Iterator<String> iter = poolHash.keySet().iterator();
       while (iter.hasNext())
       {
-        Pool p = iter.next();
-        p.pollAll(threadContext);
+        String connectionName = iter.next();
+        Pool p = poolHash.get(connectionName);
+        if (isConnectionNameValid(threadContext,connectionName))
+          p.pollAll(threadContext);
+        else
+        {
+          p.releaseAll(threadContext);
+          iter.remove();
+        }
       }
     }
 
@@ -286,7 +337,16 @@ public abstract class ConnectorPool<T ex
   public void flushUnusedConnectors(IThreadContext threadContext)
     throws ManifoldCFException
   {
-    closeAllConnectors(threadContext);
+    // Go through the whole pool and clean it out
+    synchronized (poolHash)
+    {
+      Iterator<Pool> iter = poolHash.values().iterator();
+      while (iter.hasNext())
+      {
+        Pool p = iter.next();
+        p.flushUnused(threadContext);
+      }
+    }
   }
 
   /** Clean up all open output connector handles.
@@ -305,91 +365,81 @@ public abstract class ConnectorPool<T ex
       {
         Pool p = iter.next();
         p.releaseAll(threadContext);
+        iter.remove();
       }
     }
   }
 
-  /** This is an immutable pool key class, which describes a pool in terms of two independent keys.
-  */
-  public static class PoolKey
+  // Protected methods and classes
+  
+  protected String buildServiceTypeName(String connectionName)
   {
-    protected final String className;
-    protected final ConfigParams configInfo;
-
-    /** Constructor.
-    */
-    public PoolKey(String className, Map configInfo)
-    {
-      this.className = className;
-      this.configInfo = new ConfigParams(configInfo);
-    }
-
-    public PoolKey(String className, ConfigParams configInfo)
-    {
-      this.className = className;
-      this.configInfo = configInfo;
-    }
-
-    /** Get the class name.
-    *@return the class name.
-    */
-    public String getClassName()
-    {
-      return className;
-    }
-
-    /** Get the config info.
-    *@return the params
-    */
-    public ConfigParams getParams()
-    {
-      return configInfo;
-    }
-
-    /** Hash code.
-    */
-    public int hashCode()
-    {
-      return className.hashCode() + configInfo.hashCode();
-    }
-
-    /** Equals operator.
-    */
-    public boolean equals(Object o)
-    {
-      if (!(o instanceof PoolKey))
-        return false;
-
-      PoolKey pk = (PoolKey)o;
-      return pk.className.equals(className) && pk.configInfo.equals(configInfo);
-    }
-
+    return serviceTypePrefix + connectionName;
   }
-
+  
+  protected String buildTargetCalcLockName(String connectionName)
+  {
+    return targetCalcLockPrefix + serviceTypePrefix + connectionName;
+  }
+  
   /** This class represents a value in the pool hash, which corresponds to a given key.
   */
-  public class Pool
+  protected class Pool
   {
+    /** Whether this pool is alive */
+    protected boolean isAlive = true;
+    /** The global maximum for this pool */
+    protected int globalMax;
+    /** Service type name */
+    protected final String serviceTypeName;
+    /** The (anonymous) service name */
+    protected final String serviceName;
+    /** The target calculation lock name */
+    protected final String targetCalcLockName;
+    /** Place where we keep unused connector instances */
     protected final List<T> stack = new ArrayList<T>();
-    protected final PoolKey key;
-    protected int numFree;
-
+    /** The number of local instances we can currently pass out to requesting threads.  Initially zero until pool is apportioned */
+    protected int numFree = 0;
+    /** The number of instances we are allowed to hand out locally, at this time */
+    protected int localMax = 0;
+    /** The number of instances that are actually connected and in use, as of the last poll */
+    protected int localInUse = 0;
+    
     /** Constructor
     */
-    public Pool(PoolKey pk, int maxCount)
+    public Pool(IThreadContext threadContext, int maxCount, String connectionName)
+      throws ManifoldCFException
     {
-      key = pk;
-      numFree = maxCount;
+      this.globalMax = maxCount;
+      this.targetCalcLockName = buildTargetCalcLockName(connectionName);
+      this.serviceTypeName = buildServiceTypeName(connectionName);
+      // Now, register and activate service anonymously, and record the service name we get.
+      ILockManager lockManager = LockManagerFactory.make(threadContext);
+      this.serviceName = lockManager.registerServiceBeginServiceActivity(serviceTypeName, null, null);
     }
 
+    /** Update the maximum pool size.
+    *@param maxPoolSize is the new global maximum pool size.
+    */
+    public synchronized void updateMaximumPoolSize(IThreadContext threadContext, int maxPoolSize)
+      throws ManifoldCFException
+    {
+      // This updates the maximum global size that the pool uses.
+      globalMax = maxPoolSize;
+      // We do nothing else at this time; we rely on polling to reapportion the pool.
+    }
+
+    
     /** Grab a connector.
     * If none exists, construct it using the information in the pool key.
     *@return the connector, or null if no connector could be connected.
     */
-    public synchronized T getConnector(IThreadContext threadContext)
+    public synchronized T getConnector(IThreadContext threadContext, String className, ConfigParams configParams)
       throws ManifoldCFException
     {
-      while (numFree == 0)
+      // numFree represents the number of available connector instances that have not been given out at this moment.
+      // So it's the max minus the pool count minus the number in use.
+      while (isAlive && numFree <= 0)
       {
         try
         {
@@ -400,30 +450,51 @@ public abstract class ConnectorPool<T ex
           throw new ManifoldCFException("Interrupted: "+e.getMessage(),e,ManifoldCFException.INTERRUPTED);
         }
       }
-
-      if (stack.size() == 0)
+      if (!isAlive)
+        return null;
+      
+      // We decrement numFree when we hand out a connector instance; we increment numFree when we
+      // throw away a connector instance from the pool.
+      while (true)
       {
-        String className = key.getClassName();
-        ConfigParams configParams = key.getParams();
-
-        T newrc = createConnectorInstance(threadContext,className);
-        newrc.connect(configParams);
-        stack.add(newrc);
+        if (stack.size() == 0)
+        {
+          T newrc = createConnectorInstance(threadContext,className);
+          newrc.connect(configParams);
+          stack.add(newrc);
+        }
+        
+        // Since thread context set can fail, do that before we remove it from the pool.
+        T rc = stack.remove(stack.size()-1);
+        // Set the thread context.  This can throw an exception!!  We need to be sure our bookkeeping
+        // is resilient against that possibility.  Losing a connector instance that was just sitting
+        // in the pool does NOT affect numFree, so no change needed here; we just can't disconnect the
+        // connector instance if this fails.
+        rc.setThreadContext(threadContext);
+        // Verify that the connector is in fact compatible
+        if (!(rc.getClass().getName().equals(className) && rc.getConfiguration().equals(configParams)))
+        {
+          // Looks like parameters have changed, so discard old instance.
+          try
+          {
+            rc.disconnect();
+          }
+          finally
+          {
+            rc.clearThreadContext();
+          }
+          continue;
+        }
+        // About to return a connector instance; decrement numFree accordingly.
+        numFree--;
+        return rc;
       }
-      
-      // Since thread context set can fail, do that before we remove it from the pool.
-      T rc = stack.get(stack.size()-1);
-      rc.setThreadContext(threadContext);
-      stack.remove(stack.size()-1);
-      numFree--;
-      
-      return rc;
     }
 
     /** Release a connector to the pool.
     *@param connector is the connector.
     */
-    public synchronized void releaseConnector(T connector)
+    public synchronized void releaseConnector(IThreadContext threadContext, T connector)
       throws ManifoldCFException
     {
       if (connector == null)
@@ -431,9 +502,44 @@ public abstract class ConnectorPool<T ex
 
       // Make sure connector knows it's released
       connector.clearThreadContext();
-      // Append
+      // Return it to the pool, and note that it is no longer in use.
       stack.add(connector);
       numFree++;
+      // Determine if we need to free some connectors.  If the number
+      // of allocated connectors exceeds the target, we unload some
+      // off the stack.
+      // The question is whether the stack has too many connector instances
+      // on it.  Obviously, if it stack.size() > max, it does - but remember
+      // that the number of outstanding connectors is max - numFree.
+      // So, we have an excess if stack.size() > max - (max-numFree).
+      // Simplifying: excess is when stack.size() > numFree.
+      while (stack.size() > 0 && stack.size() > numFree)
+      {
+        // Try to find a connector instance that is not actually connected.
+        // These are likely to be at the front of the queue, since those are the
+        // oldest.
+        int j;
+        for (j = 0; j < stack.size(); j++)
+        {
+          if (!stack.get(j).isConnected())
+            break;
+        }
+        T rc;
+        if (j == stack.size())
+          rc = stack.remove(stack.size()-1);
+        else
+          rc = stack.remove(j);
+        rc.setThreadContext(threadContext);
+        try
+        {
+          rc.disconnect();
+        }
+        finally
+        {
+          rc.clearThreadContext();
+        }
+      }
+
       notifyAll();
     }
 
@@ -442,37 +548,120 @@ public abstract class ConnectorPool<T ex
     public synchronized void pollAll(IThreadContext threadContext)
       throws ManifoldCFException
     {
-      int i = 0;
-      while (i < stack.size())
+      // The meat of the cross-cluster apportionment algorithm goes here!
+      // Two global numbers each service posts: "in-use" and "target".  At no time does a service *ever* post either a "target"
+      // that, together with all other active service targets, is in excess of the max.  Also, at no time a service post
+      // a target that, when added to the other "in-use" values, exceeds the max.  If the "in-use" values everywhere else
+      // already equal or exceed the max, then the target will be zero.
+      // The target quota is calculated as follows:
+      // (1) Target is summed, excluding ours.  This is GlobalTarget.
+      // (2) In-use is summed, excluding ours.  This is GlobalInUse.
+      // (3) Our MaximumTarget is computed, which is Maximum - GlobalTarget or Maximum - GlobalInUse, whichever is
+      //     smaller, but never less than zero.
+      // (4) Our FairTarget is computed.  The FairTarget divides the Maximum by the number of services, and adds
+      //     1 randomly based on the remainder.
+      // (5) We compute OptimalTarget as follows: We start with current local target.  If current local target
+      //    exceeds current local in-use count, we adjust OptimalTarget downward by one.  Otherwise we increase it
+      //    by one.
+      // (6) Finally, we compute Target by taking the minimum of MaximumTarget, FairTarget, and OptimalTarget.
+
+      ILockManager lockManager = LockManagerFactory.make(threadContext);
+      lockManager.enterWriteLock(targetCalcLockName);
+      try
       {
-        T rc = stack.get(i++);
-        // Notify
-        rc.setThreadContext(threadContext);
-        try
+        // Compute MaximumTarget
+        SumClass sumClass = new SumClass(serviceName);
+        lockManager.scanServiceData(serviceTypeName, sumClass);
+        int numServices = sumClass.getNumServices();
+        if (numServices == 0)
+          return;
+        int globalTarget = sumClass.getGlobalTarget();
+        int globalInUse = sumClass.getGlobalInUse();
+        int maximumTarget = globalMax - globalTarget;
+        if (maximumTarget > globalMax - globalInUse)
+          maximumTarget = globalMax - globalInUse;
+        if (maximumTarget < 0)
+          maximumTarget = 0;
+        
+        // Compute FairTarget
+        int fairTarget = globalMax / numServices;
+        int remainder = globalMax % numServices;
+        // Randomly choose whether we get an addition to the FairTarget
+        if (randomNumberGenerator.nextInt(numServices) < remainder)
+          fairTarget++;
+        
+        // Compute OptimalTarget (and poll connectors while we are at it)
+        int localInUse = localMax - numFree;      // These are the connectors that have been handed out
+        for (T rc : stack)
         {
-          rc.poll();
+          // Notify
+          rc.setThreadContext(threadContext);
+          try
+          {
+            rc.poll();
+            if (rc.isConnected())
+              localInUse++;       // Count every pooled connector that is still connected
+          }
+          finally
+          {
+            rc.clearThreadContext();
+          }
         }
-        finally
+        int optimalTarget = localMax;
+        if (localMax > localInUse)
+          optimalTarget--;
+        else
         {
-          rc.clearThreadContext();
+          // We want a fast ramp up, so make this proportional to globalMax
+          int increment = globalMax >> 2;
+          if (increment < 0)
+            increment = 1;
+          optimalTarget += increment;
         }
+        
+        // Now compute actual target
+        int target = maximumTarget;
+        if (target > fairTarget)
+          target = fairTarget;
+        if (target > optimalTarget)
+          target = optimalTarget;
+        
+        // Write these values to the service data variables.
+        // NOTE that there is a race condition here; the target value depends on all the calculations above being accurate, and not changing out from under us.
+        // So, that's why we have a write lock around the pool calculations.
+        
+        lockManager.updateServiceData(serviceTypeName, serviceName, pack(target, localInUse));
+        
+        // Now, update our localMax
+        if (target == localMax)
+          return;
+        // Compute the number of instances in use locally
+        localInUse = localMax - numFree;
+        localMax = target;
+        // numFree may turn out to be negative here!!  That's okay; we'll just free released connectors
+        // until we enter positive territory again.
+        numFree = localMax - localInUse;
+        notifyAll();
+      }
+      finally
+      {
+        lockManager.leaveWriteLock(targetCalcLockName);
       }
     }
 
-    /** Release all free connectors.
+    /** Flush unused connectors.
     */
-    public synchronized void releaseAll(IThreadContext threadContext)
+    public synchronized void flushUnused(IThreadContext threadContext)
       throws ManifoldCFException
     {
       while (stack.size() > 0)
       {
         // Disconnect
-        T rc = stack.get(stack.size()-1);
+        T rc = stack.remove(stack.size()-1);
         rc.setThreadContext(threadContext);
         try
         {
           rc.disconnect();
-          stack.remove(stack.size()-1);
         }
         finally
         {
@@ -481,6 +670,97 @@ public abstract class ConnectorPool<T ex
       }
     }
 
+    /** Release all free connectors.
+    */
+    public synchronized void releaseAll(IThreadContext threadContext)
+      throws ManifoldCFException
+    {
+      flushUnused(threadContext);
+      
+      // End service activity
+      isAlive = false;
+      notifyAll();
+      ILockManager lockManager = LockManagerFactory.make(threadContext);
+      lockManager.endServiceActivity(serviceTypeName, serviceName);
+    }
+
   }
 
+  protected static class SumClass implements IServiceDataAcceptor
+  {
+    protected final String serviceName;
+    protected int numServices = 0;
+    protected int globalTargetTally = 0;
+    protected int globalInUseTally = 0;
+    
+    public SumClass(String serviceName)
+    {
+      this.serviceName = serviceName;
+    }
+    
+    @Override
+    public boolean acceptServiceData(String serviceName, byte[] serviceData)
+      throws ManifoldCFException
+    {
+      numServices++;
+
+      if (!serviceName.equals(this.serviceName))
+      {
+        globalTargetTally += unpackTarget(serviceData);
+        globalInUseTally += unpackInUse(serviceData);
+      }
+      return false;
+    }
+
+    public int getNumServices()
+    {
+      return numServices;
+    }
+    
+    public int getGlobalTarget()
+    {
+      return globalTargetTally;
+    }
+    
+    public int getGlobalInUse()
+    {
+      return globalInUseTally;
+    }
+    
+  }
+  
+  protected static int unpackTarget(byte[] data)
+  {
+    if (data == null || data.length != 8)
+      return 0;
+    return ((int)data[0]) & 0xff +
+      (((int)data[1]) >> 8) & 0xff +
+      (((int)data[2]) >> 16) & 0xff +
+      (((int)data[3]) >> 24) & 0xff;
+  }
+
+  protected static int unpackInUse(byte[] data)
+  {
+    if (data == null || data.length != 8)
+      return 0;
+    return ((int)data[4]) & 0xff +
+      (((int)data[5]) >> 8) & 0xff +
+      (((int)data[6]) >> 16) & 0xff +
+      (((int)data[7]) >> 24) & 0xff;
+  }
+
+  protected static byte[] pack(int target, int inUse)
+  {
+    byte[] rval = new byte[8];
+    rval[0] = (byte)(target & 0xff);
+    rval[1] = (byte)((target >> 8) & 0xff);
+    rval[2] = (byte)((target >> 16) & 0xff);
+    rval[3] = (byte)((target >> 24) & 0xff);
+    rval[4] = (byte)(inUse & 0xff);
+    rval[5] = (byte)((inUse >> 8) & 0xff);
+    rval[6] = (byte)((inUse >> 16) & 0xff);
+    rval[7] = (byte)((inUse >> 24) & 0xff);
+    return rval;
+  }
+  
 }

Modified: manifoldcf/trunk/framework/core/src/main/java/org/apache/manifoldcf/core/database/DBInterfaceHSQLDB.java
URL: http://svn.apache.org/viewvc/manifoldcf/trunk/framework/core/src/main/java/org/apache/manifoldcf/core/database/DBInterfaceHSQLDB.java?rev=1549105&r1=1549104&r2=1549105&view=diff
==============================================================================
--- manifoldcf/trunk/framework/core/src/main/java/org/apache/manifoldcf/core/database/DBInterfaceHSQLDB.java (original)
+++ manifoldcf/trunk/framework/core/src/main/java/org/apache/manifoldcf/core/database/DBInterfaceHSQLDB.java Sun Dec  8 18:54:09 2013
@@ -142,6 +142,7 @@ public class DBInterfaceHSQLDB extends D
   public void closeDatabase()
     throws ManifoldCFException
   {
+    //System.out.println("Close database called");
     if (!isRemote)
     {
       try

Modified: manifoldcf/trunk/framework/core/src/main/java/org/apache/manifoldcf/core/interfaces/IConnector.java
URL: http://svn.apache.org/viewvc/manifoldcf/trunk/framework/core/src/main/java/org/apache/manifoldcf/core/interfaces/IConnector.java?rev=1549105&r1=1549104&r2=1549105&view=diff
==============================================================================
--- manifoldcf/trunk/framework/core/src/main/java/org/apache/manifoldcf/core/interfaces/IConnector.java (original)
+++ manifoldcf/trunk/framework/core/src/main/java/org/apache/manifoldcf/core/interfaces/IConnector.java Sun Dec  8 18:54:09 2013
@@ -64,6 +64,12 @@ public interface IConnector
   public void poll()
     throws ManifoldCFException;
 
+  /** This method is called to assess whether to count this connector instance should
+  * actually be counted as being connected.
+  *@return true if the connector instance is actually connected.
+  */
+  public boolean isConnected();
+  
   /** Close the connection.  Call this before discarding the repository connector.
   */
   public void disconnect()

Modified: manifoldcf/trunk/framework/core/src/main/java/org/apache/manifoldcf/core/interfaces/ILockManager.java
URL: http://svn.apache.org/viewvc/manifoldcf/trunk/framework/core/src/main/java/org/apache/manifoldcf/core/interfaces/ILockManager.java?rev=1549105&r1=1549104&r2=1549105&view=diff
==============================================================================
--- manifoldcf/trunk/framework/core/src/main/java/org/apache/manifoldcf/core/interfaces/ILockManager.java (original)
+++ manifoldcf/trunk/framework/core/src/main/java/org/apache/manifoldcf/core/interfaces/ILockManager.java Sun Dec  8 18:54:09 2013
@@ -44,12 +44,62 @@ public interface ILockManager
   * If registration will succeed, then this method may call an appropriate IServiceCleanup method to clean up either the
   * current service, or all services on the cluster.
   *@param serviceType is the type of service.
-  *@param serviceName is the name of the service to register.
-  *@param cleanup is called to clean up either the current service, or all services of this type, if no other active service exists
+  *@param serviceName is the name of the service to register.  If null is passed, a transient unique service name will be
+  *    created, and will be returned to the caller.
+  *@param cleanup is called to clean up either the current service, or all services of this type, if no other active service exists.
+  *    May be null.  Local service cleanup is never called if the serviceName argument is null.
+  *@return the actual service name.
   */
-  public void registerServiceBeginServiceActivity(String serviceType, String serviceName, IServiceCleanup cleanup)
+  public String registerServiceBeginServiceActivity(String serviceType, String serviceName,
+    IServiceCleanup cleanup)
     throws ManifoldCFException;
   
+  /** Register a service and begin service activity.
+  * This atomic operation creates a permanent registration entry for a service.
+  * If the permanent registration entry already exists, this method will not create it or
+  * treat it as an error.  This operation also enters the "active" zone for the service.  The "active" zone will remain in force until it is
+  * canceled, or until the process is interrupted.  Ideally, the corresponding endServiceActivity method will be
+  * called when the service shuts down.  Some ILockManager implementations require that this take place for
+  * proper management.
+  * If the transient registration already exists, it is treated as an error and an exception will be thrown.
+  * If registration will succeed, then this method may call an appropriate IServiceCleanup method to clean up either the
+  * current service, or all services on the cluster.
+  *@param serviceType is the type of service.
+  *@param serviceName is the name of the service to register.  If null is passed, a transient unique service name will be
+  *    created, and will be returned to the caller.
+  *@param initialData is the initial service data for this service.
+  *@param cleanup is called to clean up either the current service, or all services of this type, if no other active service exists.
+  *    May be null.  Local service cleanup is never called if the serviceName argument is null.
+  *@return the actual service name.
+  */
+  public String registerServiceBeginServiceActivity(String serviceType, String serviceName,
+    byte[] initialData, IServiceCleanup cleanup)
+    throws ManifoldCFException;
+
+  /** Set service data for a service.
+  *@param serviceType is the type of service.
+  *@param serviceName is the name of the service.
+  *@param serviceData is the data to update to (may be null).
+  * This updates the service's transient data (or deletes it).  If the service is not active, an exception is thrown.
+  */
+  public void updateServiceData(String serviceType, String serviceName, byte[] serviceData)
+    throws ManifoldCFException;
+
+  /** Retrieve service data for a service.
+  *@param serviceType is the type of service.
+  *@param serviceName is the name of the service.
+  *@return the service's transient data.
+  */
+  public byte[] retrieveServiceData(String serviceType, String serviceName)
+    throws ManifoldCFException;
+  
+  /** Scan service data for a service type.  Only active service data will be considered.
+  *@param serviceType is the type of service.
+  *@param dataAcceptor is the object that will be notified of each item of data for each service name found.
+  */
+  public void scanServiceData(String serviceType, IServiceDataAcceptor dataAcceptor)
+    throws ManifoldCFException;
+
   /** Count all active services of a given type.
   *@param serviceType is the service type.
   *@return the count.
@@ -89,6 +139,8 @@ public interface ILockManager
   public boolean checkServiceActive(String serviceType, String serviceName)
     throws ManifoldCFException;
 
+  /** Read specified service-associated data.  The data returned will be blank (empty) if the service
+  * is not active.
   // Configuration
   
   /** Get the current shared configuration.  This configuration is available in common among all nodes,

Modified: manifoldcf/trunk/framework/core/src/main/java/org/apache/manifoldcf/core/jdbcpool/ConnectionPoolManager.java
URL: http://svn.apache.org/viewvc/manifoldcf/trunk/framework/core/src/main/java/org/apache/manifoldcf/core/jdbcpool/ConnectionPoolManager.java?rev=1549105&r1=1549104&r2=1549105&view=diff
==============================================================================
--- manifoldcf/trunk/framework/core/src/main/java/org/apache/manifoldcf/core/jdbcpool/ConnectionPoolManager.java (original)
+++ manifoldcf/trunk/framework/core/src/main/java/org/apache/manifoldcf/core/jdbcpool/ConnectionPoolManager.java Sun Dec  8 18:54:09 2013
@@ -68,6 +68,7 @@ public class ConnectionPoolManager
   
   public void shutdown()
   {
+    //System.out.println("JDBC POOL SHUTDOWN CALLED");
     shuttingDown.set(true);
     while (connectionCloserThread.isAlive())
     {