2011-03-08 02:51:51 +01:00
// InstantBusyThread.java
2005-06-08 02:52:24 +02:00
// -----------------------
2008-07-20 19:14:51 +02:00
// (C) by Michael Peter Christen; mc@yacy.net
2005-06-08 02:52:24 +02:00
// first published on http://www.anomic.de
// Frankfurt, Germany, 2005
2011-03-08 02:51:51 +01:00
//
// $LastChangedDate$
// $LastChangedRevision$
// $LastChangedBy$
2005-06-08 02:52:24 +02:00
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2005-04-07 21:19:42 +02:00
2009-10-11 02:12:19 +02:00
package net.yacy.kelondro.workflow ;
2005-04-07 21:19:42 +02:00
2005-05-05 07:32:19 +02:00
import java.lang.reflect.InvocationTargetException ;
import java.lang.reflect.Method ;
2007-04-17 17:15:47 +02:00
import java.util.TreeMap ;
2005-04-07 21:19:42 +02:00
2013-07-09 14:28:25 +02:00
import net.yacy.cora.util.ConcurrentLog ;
2009-10-10 01:13:30 +02:00
2005-06-09 12:57:42 +02:00
2009-10-11 02:12:19 +02:00
public final class InstantBusyThread extends AbstractBusyThread implements BusyThread {
2011-11-25 12:23:52 +01:00
2006-08-18 04:07:03 +02:00
private Method jobExecMethod , jobCountMethod , freememExecMethod ;
2008-08-02 14:12:04 +02:00
private final Object environment ;
private final Long handle ;
2011-11-25 12:23:52 +01:00
2012-10-06 03:34:52 +02:00
private static final TreeMap < Long , String > jobs = new TreeMap < Long , String > ( ) ;
2011-11-25 12:23:52 +01:00
2010-03-19 16:31:15 +01:00
public InstantBusyThread (
final Object env ,
final String jobExec ,
final String jobCount ,
final String freemem ,
2011-11-25 12:23:52 +01:00
final long minIdleSleep ,
final long maxIdleSleep ,
final long minBusySleep ,
final long maxBusySleep ) {
2010-03-19 16:31:15 +01:00
super ( minIdleSleep , maxIdleSleep , minBusySleep , maxBusySleep ) ;
2011-11-25 12:23:52 +01:00
2005-06-01 16:24:25 +02:00
// jobExec is the name of a method of the object 'env' that executes the one-step-run
// jobCount is the name of a method that returns the size of the job
2006-08-18 04:07:03 +02:00
// freemem is the name of a method that tries to free memory and returns void
2009-07-01 00:20:55 +02:00
final Class < ? > theClass = ( env instanceof Class < ? > ) ? ( Class < ? > ) env : env . getClass ( ) ;
2005-04-07 21:19:42 +02:00
try {
2012-07-05 01:02:51 +02:00
this . jobExecMethod = theClass . getMethod ( jobExec ) ;
2008-08-02 14:12:04 +02:00
} catch ( final NoSuchMethodException e ) {
2005-06-01 16:24:25 +02:00
throw new RuntimeException ( " serverInstantThread, wrong declaration of jobExec: " + e . getMessage ( ) ) ;
}
try {
2005-04-07 21:19:42 +02:00
if ( jobCount = = null )
this . jobCountMethod = null ;
else
2012-07-05 01:02:51 +02:00
this . jobCountMethod = theClass . getMethod ( jobCount ) ;
2011-11-25 12:23:52 +01:00
2008-08-02 14:12:04 +02:00
} catch ( final NoSuchMethodException e ) {
2005-06-01 16:24:25 +02:00
throw new RuntimeException ( " serverInstantThread, wrong declaration of jobCount: " + e . getMessage ( ) ) ;
2005-04-07 21:19:42 +02:00
}
2006-08-18 04:07:03 +02:00
try {
if ( freemem = = null )
this . freememExecMethod = null ;
else
2012-07-05 01:02:51 +02:00
this . freememExecMethod = theClass . getMethod ( freemem ) ;
2011-11-25 12:23:52 +01:00
2008-08-02 14:12:04 +02:00
} catch ( final NoSuchMethodException e ) {
2006-08-18 04:07:03 +02:00
throw new RuntimeException ( " serverInstantThread, wrong declaration of freemem: " + e . getMessage ( ) ) ;
}
2009-07-01 00:20:55 +02:00
this . environment = ( env instanceof Class < ? > ) ? null : env ;
2014-02-28 15:02:01 +01:00
setName ( " BusyThread " + theClass . getName ( ) + " . " + jobExec ) ;
2011-11-25 12:23:52 +01:00
this . handle = Long . valueOf ( System . currentTimeMillis ( ) + getName ( ) . hashCode ( ) ) ;
2005-04-07 21:19:42 +02:00
}
2011-11-25 12:23:52 +01:00
2012-05-30 15:27:45 +02:00
@Override
2005-04-07 21:19:42 +02:00
public int getJobCount ( ) {
if ( this . jobCountMethod = = null ) return Integer . MAX_VALUE ;
try {
2012-07-05 01:02:51 +02:00
final Object result = this . jobCountMethod . invoke ( this . environment ) ;
2012-07-05 08:44:39 +02:00
return ( result instanceof Integer ) ? ( ( Integer ) result ) . intValue ( ) : - 1 ;
2008-08-02 14:12:04 +02:00
} catch ( final IllegalAccessException e ) {
2005-04-07 21:19:42 +02:00
return - 1 ;
2008-08-02 14:12:04 +02:00
} catch ( final IllegalArgumentException e ) {
2005-04-07 21:19:42 +02:00
return - 1 ;
2008-08-02 14:12:04 +02:00
} catch ( final InvocationTargetException e ) {
2013-07-09 14:28:25 +02:00
ConcurrentLog . severe ( " BUSYTHREAD " , " invocation serverInstantThread of thread ' " + getName ( ) + " ': " + e . getMessage ( ) , e ) ;
2005-04-07 21:19:42 +02:00
return - 1 ;
}
}
2011-11-25 12:23:52 +01:00
2012-05-30 15:27:45 +02:00
@Override
2005-04-07 21:19:42 +02:00
public boolean job ( ) throws Exception {
2007-04-17 17:15:47 +02:00
//System.out.println("started job " + this.handle + ": " + this.getName());
2011-11-25 12:23:52 +01:00
synchronized ( jobs ) { jobs . put ( this . handle , getName ( ) ) ; }
2005-04-07 21:19:42 +02:00
boolean jobHasDoneSomething = false ;
try {
2012-07-05 01:02:51 +02:00
final Object result = this . jobExecMethod . invoke ( this . environment ) ;
2005-04-07 21:19:42 +02:00
if ( result = = null ) jobHasDoneSomething = true ;
else if ( result instanceof Boolean ) jobHasDoneSomething = ( ( Boolean ) result ) . booleanValue ( ) ;
2008-08-02 14:12:04 +02:00
} catch ( final IllegalAccessException e ) {
2013-07-09 14:28:25 +02:00
ConcurrentLog . severe ( " BUSYTHREAD " , " Internal Error in serverInstantThread.job: " + e . getMessage ( ) ) ;
ConcurrentLog . severe ( " BUSYTHREAD " , " shutting down thread ' " + getName ( ) + " ' " ) ;
2011-11-25 12:23:52 +01:00
terminate ( false ) ;
2008-08-02 14:12:04 +02:00
} catch ( final IllegalArgumentException e ) {
2013-07-09 14:28:25 +02:00
ConcurrentLog . severe ( " BUSYTHREAD " , " Internal Error in serverInstantThread.job: " + e . getMessage ( ) ) ;
ConcurrentLog . severe ( " BUSYTHREAD " , " shutting down thread ' " + getName ( ) + " ' " ) ;
2011-11-25 12:23:52 +01:00
terminate ( false ) ;
2008-08-02 14:12:04 +02:00
} catch ( final InvocationTargetException e ) {
final String targetException = e . getTargetException ( ) . getMessage ( ) ;
2013-07-09 14:28:25 +02:00
ConcurrentLog . logException ( e ) ;
ConcurrentLog . logException ( e . getCause ( ) ) ;
ConcurrentLog . logException ( e . getTargetException ( ) ) ;
ConcurrentLog . severe ( " BUSYTHREAD " , " Runtime Error in serverInstantThread.job, thread ' " + getName ( ) + " ': " + e . getMessage ( ) + " ; target exception: " + targetException , e . getTargetException ( ) ) ;
2008-08-02 14:12:04 +02:00
} catch ( final OutOfMemoryError e ) {
2013-07-09 14:28:25 +02:00
ConcurrentLog . severe ( " BUSYTHREAD " , " OutOfMemory Error in serverInstantThread.job, thread ' " + getName ( ) + " ': " + e . getMessage ( ) ) ;
ConcurrentLog . logException ( e ) ;
2006-08-19 02:06:39 +02:00
freemem ( ) ;
2010-04-14 01:29:55 +02:00
} catch ( final Exception e ) {
2013-07-09 14:28:25 +02:00
ConcurrentLog . severe ( " BUSYTHREAD " , " Generic Exception, thread ' " + getName ( ) + " ': " + e . getMessage ( ) ) ;
ConcurrentLog . logException ( e ) ;
2005-04-07 21:19:42 +02:00
}
2007-04-17 17:15:47 +02:00
synchronized ( jobs ) { jobs . remove ( this . handle ) ; }
2005-04-07 21:19:42 +02:00
return jobHasDoneSomething ;
}
2011-11-25 12:23:52 +01:00
2012-05-30 15:27:45 +02:00
@Override
2006-08-18 04:07:03 +02:00
public void freemem ( ) {
2011-11-25 12:23:52 +01:00
if ( this . freememExecMethod = = null ) return ;
2006-08-18 04:07:03 +02:00
try {
2012-07-05 01:02:51 +02:00
this . freememExecMethod . invoke ( this . environment ) ;
2008-08-02 14:12:04 +02:00
} catch ( final IllegalAccessException e ) {
2013-07-09 14:28:25 +02:00
ConcurrentLog . severe ( " BUSYTHREAD " , " Internal Error in serverInstantThread.freemem: " + e . getMessage ( ) ) ;
ConcurrentLog . severe ( " BUSYTHREAD " , " shutting down thread ' " + getName ( ) + " ' " ) ;
2011-11-25 12:23:52 +01:00
terminate ( false ) ;
2008-08-02 14:12:04 +02:00
} catch ( final IllegalArgumentException e ) {
2013-07-09 14:28:25 +02:00
ConcurrentLog . severe ( " BUSYTHREAD " , " Internal Error in serverInstantThread.freemem: " + e . getMessage ( ) ) ;
ConcurrentLog . severe ( " BUSYTHREAD " , " shutting down thread ' " + getName ( ) + " ' " ) ;
2011-11-25 12:23:52 +01:00
terminate ( false ) ;
2008-08-02 14:12:04 +02:00
} catch ( final InvocationTargetException e ) {
final String targetException = e . getTargetException ( ) . getMessage ( ) ;
2013-07-09 14:28:25 +02:00
if ( targetException . indexOf ( " heap space " , 0 ) > 0 ) ConcurrentLog . logException ( e . getTargetException ( ) ) ;
ConcurrentLog . severe ( " BUSYTHREAD " , " Runtime Error in serverInstantThread.freemem, thread ' " + getName ( ) + " ': " + e . getMessage ( ) + " ; target exception: " + targetException , e . getTargetException ( ) ) ;
ConcurrentLog . logException ( e . getTargetException ( ) ) ;
2008-08-02 14:12:04 +02:00
} catch ( final OutOfMemoryError e ) {
2013-07-09 14:28:25 +02:00
ConcurrentLog . severe ( " BUSYTHREAD " , " OutOfMemory Error in serverInstantThread.freemem, thread ' " + getName ( ) + " ': " + e . getMessage ( ) ) ;
ConcurrentLog . logException ( e ) ;
2006-08-18 04:07:03 +02:00
}
}
2011-11-25 12:23:52 +01:00
2012-07-05 10:23:07 +02:00
public static BusyThread oneTimeJob ( final Object env , final String jobExec , final long startupDelay ) {
2005-04-07 21:19:42 +02:00
// start the job and execute it once as background process
2010-03-19 16:31:15 +01:00
final BusyThread thread = new InstantBusyThread (
env , jobExec , null , null , Long . MIN_VALUE , Long . MAX_VALUE , Long . MIN_VALUE , Long . MAX_VALUE ) ;
2005-04-07 21:19:42 +02:00
thread . setStartupSleep ( startupDelay ) ;
thread . setIdleSleep ( - 1 ) ;
thread . setBusySleep ( - 1 ) ;
2005-06-20 02:46:23 +02:00
thread . setMemPreReqisite ( 0 ) ;
2014-01-22 17:18:53 +01:00
thread . setLoadPreReqisite ( 99 ) ; // this is called during initialization phase and some code parts depend on it; therefore we cannot set a prerequisite that prevents the start of that thread
2005-04-07 21:19:42 +02:00
thread . start ( ) ;
return thread ;
}
2011-11-25 12:23:52 +01:00
2009-10-11 02:12:19 +02:00
public static WorkflowThread oneTimeJob ( final Runnable thread , final long startupDelay ) {
2012-07-05 10:23:07 +02:00
return oneTimeJob ( thread , " run " , startupDelay ) ;
2005-12-07 14:33:39 +01:00
}
2012-10-06 03:34:52 +02:00
2012-05-17 06:03:18 +02:00
@Override
public void open ( ) {
// Not implemented in this thread
}
@Override
public synchronized void close ( ) {
// Not implemented in this thread
2005-12-07 14:33:39 +01:00
}
2011-11-25 12:23:52 +01:00
2005-04-07 21:19:42 +02:00
}