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/19 03:35:13 UTC
svn commit: r1552211 - in /manifoldcf/trunk: ./
framework/api-service/src/main/java/org/apache/manifoldcf/apiservice/
framework/core/src/main/java/org/apache/manifoldcf/core/connectorpool/
framework/crawler-ui/src/main/java/org/apache/manifoldcf/crawle...
Author: kwright
Date: Thu Dec 19 02:35:13 2013
New Revision: 1552211
URL: http://svn.apache.org/r1552211
Log:
Fix for CONNECTORS-846.
Added:
manifoldcf/trunk/framework/api-service/src/main/java/org/apache/manifoldcf/apiservice/IdleCleanupThread.java (with props)
manifoldcf/trunk/framework/crawler-ui/src/main/java/org/apache/manifoldcf/crawlerui/IdleCleanupThread.java (with props)
Modified:
manifoldcf/trunk/CHANGES.txt
manifoldcf/trunk/framework/api-service/src/main/java/org/apache/manifoldcf/apiservice/ServletListener.java
manifoldcf/trunk/framework/core/src/main/java/org/apache/manifoldcf/core/connectorpool/ConnectorPool.java
manifoldcf/trunk/framework/crawler-ui/src/main/java/org/apache/manifoldcf/crawlerui/ServletListener.java
Modified: manifoldcf/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/manifoldcf/trunk/CHANGES.txt?rev=1552211&r1=1552210&r2=1552211&view=diff
==============================================================================
--- manifoldcf/trunk/CHANGES.txt (original)
+++ manifoldcf/trunk/CHANGES.txt Thu Dec 19 02:35:13 2013
@@ -3,6 +3,11 @@ $Id$
======================= 1.5-dev =====================
+CONNECTORS-846: Once a service had grabbed all connector
+instances, but was not using them any more, it would not release
+them for other cluster members to use.
+(Karl Wright)
+
CONNECTORS-844: Remove "per JVM" from connection maximum
messages in crawler UI.
(Karl Wright)
Added: manifoldcf/trunk/framework/api-service/src/main/java/org/apache/manifoldcf/apiservice/IdleCleanupThread.java
URL: http://svn.apache.org/viewvc/manifoldcf/trunk/framework/api-service/src/main/java/org/apache/manifoldcf/apiservice/IdleCleanupThread.java?rev=1552211&view=auto
==============================================================================
--- manifoldcf/trunk/framework/api-service/src/main/java/org/apache/manifoldcf/apiservice/IdleCleanupThread.java (added)
+++ manifoldcf/trunk/framework/api-service/src/main/java/org/apache/manifoldcf/apiservice/IdleCleanupThread.java Thu Dec 19 02:35:13 2013
@@ -0,0 +1,141 @@
+/* $Id$ */
+
+/**
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.apache.manifoldcf.apiservice;
+
+import org.apache.manifoldcf.core.interfaces.*;
+import org.apache.manifoldcf.agents.interfaces.*;
+import org.apache.manifoldcf.crawler.interfaces.*;
+import org.apache.manifoldcf.authorities.interfaces.*;
+import org.apache.manifoldcf.core.system.Logging;
+import org.apache.manifoldcf.core.system.ManifoldCF;
+import java.util.*;
+import java.lang.reflect.*;
+
+/** This thread periodically calls the cleanup method in all connected repository connectors. The ostensible purpose
+* is to allow the connectors to shutdown idle connections etc.
+*/
+public class IdleCleanupThread extends Thread
+{
+ public static final String _rcsid = "@(#)$Id$";
+
+ /** Constructor.
+ */
+ public IdleCleanupThread()
+ throws ManifoldCFException
+ {
+ super();
+ setName("Idle cleanup thread");
+ setDaemon(true);
+ }
+
+ public void run()
+ {
+ Logging.root.debug("Start up idle cleanup thread");
+ try
+ {
+ // Create a thread context object.
+ IThreadContext threadContext = ThreadContextFactory.make();
+ // Get the cache handle.
+ ICacheManager cacheManager = CacheManagerFactory.make(threadContext);
+
+ IRepositoryConnectorPool repositoryConnectorPool = RepositoryConnectorPoolFactory.make(threadContext);
+ IOutputConnectorPool outputConnectorPool = OutputConnectorPoolFactory.make(threadContext);
+ IAuthorityConnectorPool authorityConnectorPool = AuthorityConnectorPoolFactory.make(threadContext);
+ IMappingConnectorPool mappingConnectorPool = MappingConnectorPoolFactory.make(threadContext);
+
+ IThrottleGroups throttleGroups = ThrottleGroupsFactory.make(threadContext);
+
+ // Loop
+ while (true)
+ {
+ // Do another try/catch around everything in the loop
+ try
+ {
+ // Do the cleanup
+ repositoryConnectorPool.pollAllConnectors();
+ outputConnectorPool.pollAllConnectors();
+ authorityConnectorPool.pollAllConnectors();
+ mappingConnectorPool.pollAllConnectors();
+
+ throttleGroups.poll();
+
+ cacheManager.expireObjects(System.currentTimeMillis());
+
+ // Sleep for the retry interval.
+ ManifoldCF.sleep(5000L);
+ }
+ catch (ManifoldCFException e)
+ {
+ if (e.getErrorCode() == ManifoldCFException.INTERRUPTED)
+ break;
+
+ if (e.getErrorCode() == ManifoldCFException.DATABASE_CONNECTION_ERROR)
+ {
+ Logging.root.error("Idle cleanup thread aborting and restarting due to database connection reset: "+e.getMessage(),e);
+ try
+ {
+ // Give the database a chance to catch up/wake up
+ ManifoldCF.sleep(10000L);
+ }
+ catch (InterruptedException se)
+ {
+ break;
+ }
+ continue;
+ }
+
+ // Log it, but keep the thread alive
+ Logging.root.error("Exception tossed: "+e.getMessage(),e);
+
+ if (e.getErrorCode() == ManifoldCFException.SETUP_ERROR)
+ {
+ // Shut the whole system down!
+ System.exit(1);
+ }
+
+ }
+ catch (InterruptedException e)
+ {
+ // We're supposed to quit
+ break;
+ }
+ catch (OutOfMemoryError e)
+ {
+ System.err.println("API service ran out of memory - shutting down");
+ e.printStackTrace(System.err);
+ System.exit(-200);
+ }
+ catch (Throwable e)
+ {
+ // A more severe error - but stay alive
+ Logging.root.fatal("Error tossed: "+e.getMessage(),e);
+ }
+ }
+ }
+ catch (Throwable e)
+ {
+ // Severe error on initialization
+ System.err.println("API service could not start - shutting down");
+ Logging.root.fatal("IdleCleanupThread initialization error tossed: "+e.getMessage(),e);
+ System.exit(-300);
+ }
+
+ }
+
+}
Propchange: manifoldcf/trunk/framework/api-service/src/main/java/org/apache/manifoldcf/apiservice/IdleCleanupThread.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: manifoldcf/trunk/framework/api-service/src/main/java/org/apache/manifoldcf/apiservice/IdleCleanupThread.java
------------------------------------------------------------------------------
svn:keywords = Id
Modified: manifoldcf/trunk/framework/api-service/src/main/java/org/apache/manifoldcf/apiservice/ServletListener.java
URL: http://svn.apache.org/viewvc/manifoldcf/trunk/framework/api-service/src/main/java/org/apache/manifoldcf/apiservice/ServletListener.java?rev=1552211&r1=1552210&r2=1552211&view=diff
==============================================================================
--- manifoldcf/trunk/framework/api-service/src/main/java/org/apache/manifoldcf/apiservice/ServletListener.java (original)
+++ manifoldcf/trunk/framework/api-service/src/main/java/org/apache/manifoldcf/apiservice/ServletListener.java Thu Dec 19 02:35:13 2013
@@ -29,11 +29,16 @@ public class ServletListener implements
{
public static final String _rcsid = "@(#)$Id$";
+ protected IdleCleanupThread idleCleanupThread = null;
+
public void contextInitialized(ServletContextEvent sce)
{
try
{
- ManifoldCF.initializeEnvironment(ThreadContextFactory.make());
+ IThreadContext threadContext = ThreadContextFactory.make();
+ ManifoldCF.initializeEnvironment(threadContext);
+ idleCleanupThread = new IdleCleanupThread();
+ idleCleanupThread.start();
}
catch (ManifoldCFException e)
{
@@ -43,7 +48,21 @@ public class ServletListener implements
public void contextDestroyed(ServletContextEvent sce)
{
- ManifoldCF.cleanUpEnvironment(ThreadContextFactory.make());
+ try
+ {
+ while (true)
+ {
+ if (idleCleanupThread == null)
+ break;
+ idleCleanupThread.interrupt();
+ if (!idleCleanupThread.isAlive())
+ idleCleanupThread = null;
+ }
+ }
+ finally
+ {
+ ManifoldCF.cleanUpEnvironment(ThreadContextFactory.make());
+ }
}
}
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=1552211&r1=1552210&r2=1552211&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 Thu Dec 19 02:35:13 2013
@@ -621,7 +621,7 @@ public abstract class ConnectorPool<T ex
optimalTarget += increment;
}
- //System.out.println("maxTarget = "+maximumTarget+"; fairTarget = "+fairTarget+"; optimalTarget = "+optimalTarget);
+ //System.out.println(serviceTypeName+":maxTarget = "+maximumTarget+"; fairTarget = "+fairTarget+"; optimalTarget = "+optimalTarget);
// Now compute actual target
int target = maximumTarget;
@@ -630,6 +630,7 @@ public abstract class ConnectorPool<T ex
if (target > optimalTarget)
target = optimalTarget;
+ //System.out.println(serviceTypeName+":Picking target="+target+"; localInUse="+localInUse);
// 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.
@@ -639,6 +640,7 @@ public abstract class ConnectorPool<T ex
// Now, update our localMax
if (target == localMax)
return;
+ //System.out.println(serviceTypeName+":Updating target: "+target);
// Compute the number of instances in use locally
localInUse = localMax - numFree;
localMax = target;
@@ -651,6 +653,35 @@ public abstract class ConnectorPool<T ex
{
lockManager.leaveWriteLock(targetCalcLockName);
}
+
+ // Finally, free pooled instances in excess of target
+ 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();
+ }
+ }
+
}
/** Flush unused connectors.
Added: manifoldcf/trunk/framework/crawler-ui/src/main/java/org/apache/manifoldcf/crawlerui/IdleCleanupThread.java
URL: http://svn.apache.org/viewvc/manifoldcf/trunk/framework/crawler-ui/src/main/java/org/apache/manifoldcf/crawlerui/IdleCleanupThread.java?rev=1552211&view=auto
==============================================================================
--- manifoldcf/trunk/framework/crawler-ui/src/main/java/org/apache/manifoldcf/crawlerui/IdleCleanupThread.java (added)
+++ manifoldcf/trunk/framework/crawler-ui/src/main/java/org/apache/manifoldcf/crawlerui/IdleCleanupThread.java Thu Dec 19 02:35:13 2013
@@ -0,0 +1,141 @@
+/* $Id$ */
+
+/**
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.apache.manifoldcf.crawlerui;
+
+import org.apache.manifoldcf.core.interfaces.*;
+import org.apache.manifoldcf.agents.interfaces.*;
+import org.apache.manifoldcf.crawler.interfaces.*;
+import org.apache.manifoldcf.authorities.interfaces.*;
+import org.apache.manifoldcf.core.system.Logging;
+import org.apache.manifoldcf.core.system.ManifoldCF;
+import java.util.*;
+import java.lang.reflect.*;
+
+/** This thread periodically calls the cleanup method in all connected repository connectors. The ostensible purpose
+* is to allow the connectors to shutdown idle connections etc.
+*/
+public class IdleCleanupThread extends Thread
+{
+ public static final String _rcsid = "@(#)$Id$";
+
+ /** Constructor.
+ */
+ public IdleCleanupThread()
+ throws ManifoldCFException
+ {
+ super();
+ setName("Idle cleanup thread");
+ setDaemon(true);
+ }
+
+ public void run()
+ {
+ Logging.root.debug("Start up idle cleanup thread");
+ try
+ {
+ // Create a thread context object.
+ IThreadContext threadContext = ThreadContextFactory.make();
+ // Get the cache handle.
+ ICacheManager cacheManager = CacheManagerFactory.make(threadContext);
+
+ IRepositoryConnectorPool repositoryConnectorPool = RepositoryConnectorPoolFactory.make(threadContext);
+ IOutputConnectorPool outputConnectorPool = OutputConnectorPoolFactory.make(threadContext);
+ IAuthorityConnectorPool authorityConnectorPool = AuthorityConnectorPoolFactory.make(threadContext);
+ IMappingConnectorPool mappingConnectorPool = MappingConnectorPoolFactory.make(threadContext);
+
+ IThrottleGroups throttleGroups = ThrottleGroupsFactory.make(threadContext);
+
+ // Loop
+ while (true)
+ {
+ // Do another try/catch around everything in the loop
+ try
+ {
+ // Do the cleanup
+ repositoryConnectorPool.pollAllConnectors();
+ outputConnectorPool.pollAllConnectors();
+ authorityConnectorPool.pollAllConnectors();
+ mappingConnectorPool.pollAllConnectors();
+
+ throttleGroups.poll();
+
+ cacheManager.expireObjects(System.currentTimeMillis());
+
+ // Sleep for the retry interval.
+ ManifoldCF.sleep(5000L);
+ }
+ catch (ManifoldCFException e)
+ {
+ if (e.getErrorCode() == ManifoldCFException.INTERRUPTED)
+ break;
+
+ if (e.getErrorCode() == ManifoldCFException.DATABASE_CONNECTION_ERROR)
+ {
+ Logging.root.error("Idle cleanup thread aborting and restarting due to database connection reset: "+e.getMessage(),e);
+ try
+ {
+ // Give the database a chance to catch up/wake up
+ ManifoldCF.sleep(10000L);
+ }
+ catch (InterruptedException se)
+ {
+ break;
+ }
+ continue;
+ }
+
+ // Log it, but keep the thread alive
+ Logging.root.error("Exception tossed: "+e.getMessage(),e);
+
+ if (e.getErrorCode() == ManifoldCFException.SETUP_ERROR)
+ {
+ // Shut the whole system down!
+ System.exit(1);
+ }
+
+ }
+ catch (InterruptedException e)
+ {
+ // We're supposed to quit
+ break;
+ }
+ catch (OutOfMemoryError e)
+ {
+ System.err.println("Crawler UI ran out of memory - shutting down");
+ e.printStackTrace(System.err);
+ System.exit(-200);
+ }
+ catch (Throwable e)
+ {
+ // A more severe error - but stay alive
+ Logging.root.fatal("Error tossed: "+e.getMessage(),e);
+ }
+ }
+ }
+ catch (Throwable e)
+ {
+ // Severe error on initialization
+ System.err.println("Crawler UI could not start - shutting down");
+ Logging.root.fatal("IdleCleanupThread initialization error tossed: "+e.getMessage(),e);
+ System.exit(-300);
+ }
+
+ }
+
+}
Propchange: manifoldcf/trunk/framework/crawler-ui/src/main/java/org/apache/manifoldcf/crawlerui/IdleCleanupThread.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: manifoldcf/trunk/framework/crawler-ui/src/main/java/org/apache/manifoldcf/crawlerui/IdleCleanupThread.java
------------------------------------------------------------------------------
svn:keywords = Id
Modified: manifoldcf/trunk/framework/crawler-ui/src/main/java/org/apache/manifoldcf/crawlerui/ServletListener.java
URL: http://svn.apache.org/viewvc/manifoldcf/trunk/framework/crawler-ui/src/main/java/org/apache/manifoldcf/crawlerui/ServletListener.java?rev=1552211&r1=1552210&r2=1552211&view=diff
==============================================================================
--- manifoldcf/trunk/framework/crawler-ui/src/main/java/org/apache/manifoldcf/crawlerui/ServletListener.java (original)
+++ manifoldcf/trunk/framework/crawler-ui/src/main/java/org/apache/manifoldcf/crawlerui/ServletListener.java Thu Dec 19 02:35:13 2013
@@ -29,11 +29,16 @@ public class ServletListener implements
{
public static final String _rcsid = "@(#)$Id$";
+ protected IdleCleanupThread idleCleanupThread = null;
+
public void contextInitialized(ServletContextEvent sce)
{
try
{
- ManifoldCF.initializeEnvironment(ThreadContextFactory.make());
+ IThreadContext threadContext = ThreadContextFactory.make();
+ ManifoldCF.initializeEnvironment(threadContext);
+ idleCleanupThread = new IdleCleanupThread();
+ idleCleanupThread.start();
}
catch (ManifoldCFException e)
{
@@ -43,7 +48,21 @@ public class ServletListener implements
public void contextDestroyed(ServletContextEvent sce)
{
- ManifoldCF.cleanUpEnvironment(ThreadContextFactory.make());
+ try
+ {
+ while (true)
+ {
+ if (idleCleanupThread == null)
+ break;
+ idleCleanupThread.interrupt();
+ if (!idleCleanupThread.isAlive())
+ idleCleanupThread = null;
+ }
+ }
+ finally
+ {
+ ManifoldCF.cleanUpEnvironment(ThreadContextFactory.make());
+ }
}
}