head	1.37;
access;
symbols
	TIGRIS_1_1_0RC2:1.6
	TIGRIS_1_1_0RC1:1.6
	TIGRIS_1_1:1.6.0.4
	TIGRIS_1_0_8:1.6
	TIGRIS_1_0_8RC3:1.6
	TIGRIS_1_0_8RC2:1.6
	TIGRIS_1_0_8RC1:1.6
	TIGRIS_1_0_7:1.6
	TIGRIS_1_0_7RC3:1.6
	TIGRIS_1_0_7RC2:1.6
	TIGRIS_1_0_7RC1:1.6
	TIGRIS_1_0_6:1.6
	TIGRIS_1_0_6RC5:1.6
	TIGRIS_1_0_6RC4:1.6
	TIGRIS_1_0_6RC3:1.6
	TIGRIS_1_0_6RC2:1.6
	TIGRIS_1_0_6RC1:1.6
	TIGRIS_1_0_5:1.6
	TIGRIS_1_0_5RC6:1.6
	TIGRIS_1_0_5RC5:1.6
	TIGRIS_1_0_5RC4:1.6
	TIGRIS_1_0_5RC3:1.6
	TIGRIS_1_0_5RC2:1.6
	TIGRIS_1_0_5RC1:1.6
	TIGRIS_1_0_4:1.6
	TIGRIS_1_0_3:1.6
	TIGRIS_1_0_2:1.6
	TIGRIS_1_0_1:1.6
	TIGRIS_1_0:1.6.0.6
	TIGRIS_1_0_0:1.6
	TIGRIS_1_0_0_RC1:1.6.0.2;
locks; strict;
comment	@# @;


1.37
date	2001.08.20.17.13.12;	author leonardr;	state Exp;
branches;
next	1.36;

1.36
date	2001.08.20.17.11.38;	author leonardr;	state Exp;
branches;
next	1.35;

1.35
date	2001.08.17.19.02.19;	author leonardr;	state Exp;
branches;
next	1.34;

1.34
date	2001.08.17.18.17.09;	author leonardr;	state Exp;
branches;
next	1.33;

1.33
date	2001.08.11.09.08.10;	author dlr;	state Exp;
branches;
next	1.32;

1.32
date	2001.07.31.00.17.08;	author dlr;	state Exp;
branches;
next	1.31;

1.31
date	2001.07.30.23.26.31;	author dlr;	state Exp;
branches;
next	1.30;

1.30
date	2001.06.25.21.35.43;	author leonardr;	state Exp;
branches;
next	1.29;

1.29
date	2001.06.15.19.39.47;	author edk;	state Exp;
branches;
next	1.28;

1.28
date	2001.06.07.01.58.21;	author leonardr;	state Exp;
branches;
next	1.27;

1.27
date	2001.05.31.02.41.37;	author leonardr;	state Exp;
branches;
next	1.26;

1.26
date	2001.05.22.20.34.56;	author leonardr;	state Exp;
branches;
next	1.25;

1.25
date	2001.05.18.21.56.26;	author leonardr;	state Exp;
branches;
next	1.24;

1.24
date	2001.05.02.19.22.53;	author dlr;	state Exp;
branches;
next	1.23;

1.23
date	2001.04.18.22.39.20;	author dlr;	state Exp;
branches;
next	1.22;

1.22
date	2001.04.12.19.10.15;	author dlr;	state Exp;
branches;
next	1.21;

1.21
date	2001.04.12.19.09.59;	author dlr;	state Exp;
branches;
next	1.20;

1.20
date	2001.04.12.00.43.31;	author leonardr;	state Exp;
branches;
next	1.19;

1.19
date	2001.04.11.23.54.33;	author leonardr;	state Exp;
branches;
next	1.18;

1.18
date	2001.04.11.23.47.56;	author dlr;	state Exp;
branches;
next	1.17;

1.17
date	2001.04.11.23.38.45;	author leonardr;	state Exp;
branches;
next	1.16;

1.16
date	2001.04.11.22.43.17;	author dlr;	state Exp;
branches;
next	1.15;

1.15
date	2001.04.11.22.19.42;	author dlr;	state Exp;
branches;
next	1.14;

1.14
date	2001.04.11.21.53.15;	author dlr;	state Exp;
branches;
next	1.13;

1.13
date	2001.04.11.03.31.02;	author dlr;	state Exp;
branches;
next	1.12;

1.12
date	2001.04.06.20.51.22;	author dlr;	state Exp;
branches;
next	1.11;

1.11
date	2001.04.06.20.40.22;	author leonardr;	state Exp;
branches;
next	1.10;

1.10
date	2001.04.06.20.32.26;	author dlr;	state Exp;
branches;
next	1.9;

1.9
date	2001.04.06.20.27.42;	author leonardr;	state Exp;
branches;
next	1.8;

1.8
date	2001.04.06.20.12.59;	author dlr;	state Exp;
branches;
next	1.7;

1.7
date	2001.04.06.20.05.29;	author leonardr;	state Exp;
branches;
next	1.6;

1.6
date	2001.03.26.18.33.55;	author leonardr;	state Exp;
branches;
next	1.5;

1.5
date	2001.03.26.17.37.01;	author leonardr;	state Exp;
branches;
next	1.4;

1.4
date	2001.03.16.23.16.55;	author leonardr;	state Exp;
branches;
next	1.3;

1.3
date	2001.03.16.17.28.14;	author dlr;	state Exp;
branches;
next	1.2;

1.2
date	2001.03.16.17.25.02;	author dlr;	state Exp;
branches;
next	1.1;

1.1
date	2001.03.14.02.35.53;	author dlr;	state Exp;
branches;
next	;


desc
@@


1.37
log
@Corrected more JavaDoc.
@
text
@/* ================================================================
 * Copyright (c) 2000-2001 CollabNet.  All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 * 
 * 1. Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 * 
 * 2. Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * 
 * 3. The end-user documentation included with the redistribution, if
 * any, must include the following acknowlegement: "This product includes
 * software developed by CollabNet (http://www.collab.net/)."
 * Alternately, this acknowlegement may appear in the software itself, if
 * and wherever such third-party acknowlegements normally appear.
 * 
 * 4. The hosted project names must not be used to endorse or promote
 * products derived from this software without prior written
 * permission. For written permission, please contact info@@collab.net.
 * 
 * 5. Products derived from this software may not use the "Tigris" name
 * nor may "Tigris" appear in their names without prior written
 * permission of CollabNet.
 * 
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL COLLABNET OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * ====================================================================
 * 
 * This software consists of voluntary contributions made by many
 * individuals on behalf of CollabNet.
 */


package org.tigris.helm.tool.task;

import java.util.*;

import org.apache.commons.util.exception.NestableException;

import org.apache.fulcrum.BaseService;
import org.apache.fulcrum.InitializationException;
import org.apache.fulcrum.ServiceException;
import org.apache.fulcrum.TurbineServices;

import org.tigris.helm.om.Task;
import org.tigris.helm.tool.HelmEmailer;
import org.tigris.helm.tool.cluster.ClusteredSingletonService;
import org.apache.turbine.util.Log;

/**
 * Runs tasks until there are no more, then sleeps until more are queued.
 * A cluster-wide singleton.
 *
 * Use of <code>Thread.stop()</code> is avoided as <a href="http://java.sun.com/products/jdk//1.2/docs/guide/misc/threadPrimitiveDeprecation.html">described
 * by JavaSoft</a>.
 *
 * @@author <a href="mailto:dlr@@collab.net">Daniel Rall</a>
 * @@author <a href="mailto:leonardr@@collab.net">Leonard Richardson</a>
 * @@version $Id: TaskRunnerService.java,v 1.36 2001/08/20 17:11:38 leonardr Exp $
 */
public class TaskRunnerService extends ClusteredSingletonService
{
    /**
     * Whether or not to log debugging information
     */
    private static final boolean DEBUG = false;

    /**
     * The name of this service.  Used to retrive it from the broker.
     */
    public static final String SERVICE_NAME = "TaskRunnerService";

    /**
     * The thread which actually runs tasks.
     */
    TaskRunner taskRunner;

    /**
     * A wrapper method for getting the single instance of this
     * service from the Turbine services list.
     *
     * @@return Turbine's single instance of this service.
     */
    public static final TaskRunnerService getService()
    {
        return (TaskRunnerService) TurbineServices
            .getInstance().getService(TaskRunnerService.SERVICE_NAME);
    }

    /**
     * Constructor; initialize to not being the singleton.
     */
    public TaskRunnerService()
    {
        isSingleton = false;
    }

    /**
     * Descriptor for this singleton.
     */
    public final String getDescriptor()
    {
        return SERVICE_NAME;
    }

    /**
     * Initializes this service.  Called during Fulcrum
     * initialization.
     */
    public synchronized void init()
        throws InitializationException
    {
        super.init();
        taskRunner = new TaskRunner();
        Thread runnerThread = new Thread(taskRunner);
        runnerThread.start();
    }

    /**
     * Returns the status of this service. 
     */
    public final String getStatus()
        throws ServiceException
    {
        int queuedTasks = 0;
        int runCount = taskRunner.runCount;
        int failureCount = taskRunner.failureCount;

        try
        {
            queuedTasks = Task.getTasks().size();
        }
        catch (Exception e)
        {
            throw new ServiceException(e);
        }
        StringBuffer b = new StringBuffer("").append(queuedTasks)
            .append(" queued task")
            .append(queuedTasks==1 ? "" : "s").append(".\n");

        b.append(runCount)
            .append(" task")
            .append(runCount==1 ? "" : "s").append(" successfully run, ")
            .append(failureCount).append(" failure")
            .append(failureCount==1 ? "" : "s")
            .append(".\n");
        
        return b.toString();
    }

    /**
     * The class which actually runs the tasks.
     */
    private class TaskRunner implements Runnable
    {
  
        /**
         * The number of tasks which have been run
         */
        private  int runCount = 0;
        
        /**
         * The number of task failures which have occured.
         */
        private int failureCount = 0;
      
        /**
         * Task runner loop.
         */
        public void run()
        {
            while (true)
            {
                if (isSingleton)
                {
                    try
                    {                    
                        doService();
                    }
                    catch (Exception e)
                    {
                        Log.error(e);
                    }
                }
                try
                {
                    Thread.sleep(5000);
                }
                catch (InterruptedException ignore)
                {
                    //Back to work.
                }
            }
        }

        /**
         * Runs all current tasks in the HELM_TASK table. 
         */
        public void doService()
            throws Exception
        {
            List tasksToRun = null;
            Task t = null;
            tasksToRun = Task.getTasks();
            if (!tasksToRun.isEmpty())
            {
                logTasks(tasksToRun);
                
                // Run each task in the batch.
                try 
                {
                    int taskno = 0;
                    for (ListIterator i = tasksToRun.listIterator(); 
                         i.hasNext();)
                    {                            
                        if (stop) 
                        {
                            break;
                        }
                        t = (Task)i.next();
                        if (DEBUG)
                        {
                            Log.debug("Running task " + t.getTaskId() + 
                                      ": " + t.getComponent() + "::" + 
                                      t.getCommand());
                        }                    
                        Task.runTask(t);
                        runCount++;
                        if (stop)
                        {
                            break;
                        }
                    }
                } 
                catch (TaskException e) 
                {
                    failureCount++;
                    Log.error("task failed", e);
                    //Send email to the host admin(s).
                    String description = "";
                    try
                    {
                        if (t != null)
                        {
                            description = t.getComponent() + " / " +
                                t.getCommand() + " (TaskID: " + t.getTaskId() +
                                ", AffectedObjectID : " + t.getAffectedObjectId() +
                                ")";
                        }
                    }
                    catch (Exception ignored) {}
                    String subject = "Update script failed.";
                    String body = 
                        "Execution of the following task failed: '"
                        + description + "' :\n\n" + e.getMessage();
                    
                    HelmEmailer emailer = new HelmEmailer();
                    emailer.sendError(subject, body);
                }
            }
        }
    

        /**
         * Prints a summary of the currently queued tasks.
         */
        public void logTasks(List tasks)
        {
            if (!DEBUG) return;
            Log.debug("--------------------------------------");
            Log.debug("TaskRunner has tasks to perform!");
            Log.debug("Task summary for this round:");
            int oldTypeNumber = 1;
            String oldType = "";
            
            //Display at most MAX_TASK_SETS_TO_LOG sets of tasks. 20 instances
            //of a Component::Task task will be displayed as
            //"Component::Task (20x)". The last set of tasks in the list
            //is printed outside the loop.
            for (Iterator i = tasks.iterator(); i.hasNext();)
            {                        
                Task t = (Task)i.next();
                String newType = t.getComponent() + "::" + t.getCommand();
                if (newType.equals(oldType))
                {
                    oldTypeNumber++;
                } 
                else 
                {
                    if (!oldType.equals(""))
                    {
                        if (oldTypeNumber == 1)
                        {
                            Log.debug(oldType);
                        } 
                        else 
                        {
                            Log.debug(oldType + " (" + oldTypeNumber + "x)");
                        }
                    }
                    oldType = newType;
                    oldTypeNumber = 1;
                }
            }

            //Display the last set of tasks.
            if (oldTypeNumber == 1)
            {
                Log.debug(oldType);
            } else {
                Log.debug(oldType + " (" + oldTypeNumber + "x)");
            }            
            Log.debug("--------------------------------------");
        }
    }
}
@


1.36
log
@Corrected JavaDoc.
@
text
@d73 1
a73 1
 * @@version $Id: TaskRunnerService.java,v 1.35 2001/08/17 19:02:19 leonardr Exp $
d211 1
a211 3
         * This method is called every time the singleton reasserts itself
         * as the singleton. It runs all current tasks in the HELM_TASK
         * table. 
@


1.35
log
@The doService method hasn't been used by ClusteredSingletonService in quite a while.
@
text
@d73 1
a73 1
 * @@version $Id: TaskRunnerService.java,v 1.34 2001/08/17 18:17:09 leonardr Exp $
d88 1
a88 2
     * Whether the thread version of this service is the event listener
     * or the task runner.
@


1.34
log
@Cleaned up election irregularities (which required a patch to Spread) and got the TaskRunner working again.
@
text
@d73 1
a73 1
 * @@version $Id: TaskRunnerService.java,v 1.33 2001/08/11 09:08:10 dlr Exp $
a163 5
    }

    public void doService()
    {

@


1.33
log
@Upgrading to Turbine 3.0-dev, Fulcrum 1.0, and Torque 1.0.
@
text
@d73 1
a73 1
 * @@version $Id: TaskRunnerService.java,v 1.32 2001/07/31 00:17:08 dlr Exp $
d88 2
a89 1
     * The number of tasks which have been run
d91 1
a91 6
    private static int runCount = 0;

    /**
     * The number of task failures which have occured.
     */
    private static int failureCount = 0;
d122 13
d141 3
d166 5
d172 1
a172 3
     * This method is called every time the singleton reasserts itself
     * as the singleton. It runs all current tasks in the HELM_TASK
     * table. 
d174 1
a174 2
    public void doService()
        throws Exception
d176 15
a190 4
        List tasksToRun = null;
        Task t = null;
        tasksToRun = Task.getTasks();
        if (!tasksToRun.isEmpty())
d192 1
a192 4
            logTasks(tasksToRun);
            
            // Run each task in the batch.
            try 
d194 5
a198 7
                int taskno = 0;
                for (ListIterator i = tasksToRun.listIterator(); 
                     i.hasNext();)
                {                            
                    if (stop) 
                    {
                        break;
d200 1
a200 10
                    t = (Task)i.next();
                    if (DEBUG)
                    {
                        Log.debug("Running task " + t.getTaskId() + 
                                  ": " + t.getComponent() + "::" + 
                                  t.getCommand());
                    }                    
                    Task.runTask(t);
                    runCount++;
                    if (stop)
d202 1
a202 1
                        break;
a204 7
            } 
            catch (TaskException e) 
            {
                failureCount++;
                Log.error("task failed", e);
                //Send email to the host admin(s).
                String description = "";
d207 5
a211 7
                    if (t != null)
                    {
                        description = t.getComponent() + " / " +
                            t.getCommand() + " (TaskID: " + t.getTaskId() +
                            ", AffectedObjectID : " + t.getAffectedObjectId() +
                            ")";
                    }
a212 8
                catch (Exception ignored) {}
                String subject = "Update script failed.";
                String body = 
                    "Execution of the following task failed: '"
                    + description + "' :\n\n" + e.getMessage();
                
                HelmEmailer emailer = new HelmEmailer();
                emailer.sendError(subject, body);
a214 1
    }
d216 12
a227 21
    /**
     * Prints a summary of the currently queued tasks.
     */
    public void logTasks(List tasks)
    {
        if (!DEBUG) return;
        Log.debug("--------------------------------------");
        Log.debug("TaskRunner has tasks to perform!");
        Log.debug("Task summary for this round:");
        int oldTypeNumber = 1;
        String oldType = "";

        //Display at most MAX_TASK_SETS_TO_LOG sets of tasks. 20 instances
        //of a Component::Task task will be displayed as
        //"Component::Task (20x)". The last set of tasks in the list
        //is printed outside the loop.
        for (Iterator i = tasks.iterator(); i.hasNext();)
        {                        
            Task t = (Task)i.next();
            String newType = t.getComponent() + "::" + t.getCommand();
            if (newType.equals(oldType))
d229 29
a257 5
                oldTypeNumber++;
            } 
            else 
            {
                if (!oldType.equals(""))
d259 5
a263 1
                    if (oldTypeNumber == 1)
d265 7
a271 5
                        Log.debug(oldType);
                    } 
                    else 
                    {
                        Log.debug(oldType + " (" + oldTypeNumber + "x)");
d273 8
a281 2
                oldType = newType;
                oldTypeNumber = 1;
d284 1
d286 4
a289 2
        //Display the last set of tasks.
        if (oldTypeNumber == 1)
d291 46
a336 5
            Log.debug(oldType);
        } else {
            Log.debug(oldType + " (" + oldTypeNumber + "x)");
        }            
        Log.debug("--------------------------------------");
@


1.32
log
@* Removed unused import of DBConnection, and moved
ClusteredSingletonService into alphabetical order.

* Removed getTimeout() method, and moved getDescriptor() further down.

* Removed extraneous whitespace.
@
text
@a50 1
import javax.servlet.ServletConfig;
d52 6
a57 3
import org.apache.turbine.services.*;
import org.apache.turbine.util.Log;
import org.apache.turbine.util.TurbineException;
d62 1
d73 1
a73 1
 * @@version $Id: TaskRunnerService.java,v 1.31 2001/07/30 23:26:31 dlr Exp $
d105 1
a105 1
        return (TaskRunnerService)TurbineServices
d129 1
a129 1
        throws TurbineException
d138 1
a138 1
            throw new TurbineException(e);
@


1.31
log
@Removed unused {START,STOP}_TIME constants.
@
text
@a53 1
import org.apache.turbine.util.db.pool.DBConnection;
a56 1
import org.tigris.helm.tool.cluster.ClusteredSingletonService;
d59 1
d70 1
a70 1
 * @@version $Id: TaskRunnerService.java,v 1.30 2001/06/25 21:35:43 leonardr Exp $
a84 17
     * Descriptor for this singleton's timestamp event.
     */
    public final String getDescriptor()
    {
        return SERVICE_NAME;
    }

    /**
     * Returns the time, in milliseconds, which must elapse before a
     * claim on a singleton is considered dead.
     */
    public long getTimeout()
    {
        return 1000 * 60;
    }

    /**
d115 8
a270 1

@


1.30
log
@Got rid of whitespace.
@
text
@d71 1
a71 1
 * @@version $Id: TaskRunnerService.java,v 1.29 2001/06/15 19:39:47 edk Exp $
a83 11

    /**
     * How long the taskrunner is given to stop before an error occurs.
     */
    private static final long STOP_TIME = 3500;

    /**
     * How long the taskrunner must stay alive after being started
     * without an error occuring.
     */
    private static final long START_TIME = 3500;
@


1.29
log
@provide better debugging information when tasks fail
@
text
@d71 1
a71 1
 * @@version $Id: TaskRunnerService.java,v 1.28 2001/06/07 01:58:21 leonardr Exp $
a212 6





    
@


1.28
log
@Added placeholder HelmService interface.
@
text
@d71 1
a71 1
 * @@version $Id: TaskRunnerService.java,v 1.27 2001/05/31 02:41:37 leonardr Exp $
d181 1
d198 1
a198 1
                    Task t = (Task)i.next();
d213 6
d221 2
d224 12
a235 1
                failureCount++;
d238 2
a239 2
                    "Execution of the following task failed:\n\n"
                    + e.getMessage();
@


1.27
log
@Factored out script running code to support new IssueTrackingRebuildService.
@
text
@d56 1
d71 1
a71 1
 * @@version $Id: TaskRunnerService.java,v 1.26 2001/05/22 20:34:56 leonardr Exp $
d114 10
d144 29
d203 1
a203 1
                    }
d205 1
d215 1
@


1.26
log
@Changed poll time and singleton timeout to be more configurable.
@
text
@d70 1
a70 1
 * @@version $Id: TaskRunnerService.java,v 1.25 2001/05/18 21:56:26 leonardr Exp $
a157 30
                    
                    //HACK: Condense multiple runs of "rebuild
                    //issue tracking" for the same project"
                    //into one run.
                    if ("Helm".equals(t.getComponent()) && 
                        "Rebuild Issue Tracking".equals(t.getCommand()))
                    {
                        String projectID = t.getAffectedObjectID();
                        boolean keepGoing = true;
                        while(keepGoing && i.hasNext())
                        {                                    
                            Task t2 = (Task)tasksToRun.get(i.nextIndex());
                            String id2 = t2.getAffectedObjectID();
                            String component2 = t2.getComponent();
                            String command2 = t2.getCommand();
                            if ("Helm".equals(component2) && 
                                "Rebuild Issue Tracking".equals
                                (command2) &&
                                projectID.equals(id2))
                            {
                                t.setAsDone();
                                t = (Task)i.next();
                            }
                            else
                            {
                                keepGoing = false;
                            }
                        }
                    }
                    
@


1.25
log
@Fixed up cluster singleton interface and made the task runner into a cluster singleton.
@
text
@d70 1
a70 1
 * @@version $Id: TaskRunnerService.java,v 1.24 2001/05/02 19:22:53 dlr Exp $
d101 9
@


1.24
log
@Added getService() wrapper method.
@
text
@a50 1
import java.rmi.RemoteException;
d54 1
d57 3
a59 1
import org.tigris.helm.tool.cluster.*;
d62 5
a66 2
 * Starts up and controls Helm's <code>TaskRunner</code> thread.  User
 * interface for manual control provided by <code>AdminUtils</code>.
d70 1
a70 1
 * @@version $Id: TaskRunnerService.java,v 1.23 2001/04/18 22:39:20 dlr Exp $
d72 1
a72 2
public class TaskRunnerService extends BaseUnicastRemoteService
    implements TaskRunnerServiceSpec
d75 5
d96 1
a96 2
     * The thread which runs batches of tasks for this service (across the
     * cluster).
d98 4
a101 8
    private TaskRunner taskRunner;

    /**
     * The name of the logfile to which the thread writes.
     */
    private String logFile;

    private boolean isSingleton;
d115 3
a118 1
        throws RemoteException
d124 21
a144 148
     * Called during <code>Turbine.init()</code> (i.e. early initialization).
     *
     * @@param config The configuration we're operating under.
     */
    public void init(ServletConfig config)
        throws InitializationException
    {
        Properties props = getProperties();
        logFile = props.getProperty("logFile");
        try 
        {
            register();
            setInit(true);
        }
        catch (RemoteException e)
        {
            Log.error(SERVICE_NAME + " registration with cluster mediator " +
                      "failed", e);
            Log.debug("Stack trace:", e);
            // HELP: Should we send a stop signal if we have a live thread?
        }
    }

    /**
     * Register with the Mediator. A SingletonRecognitionEvent may be
     * sent to me in response.
     */
    public void register()
        throws RemoteException
    {
        try
        {
            Log.debug(SERVICE_NAME + ": Attempting registration w/ mediator");
            getMediator().register(this);
        }
        catch (Exception e)
        {
            Log.error(e);
            throw new RemoteException(SERVICE_NAME + ": Registration with " +
                                      "mediator failed: " + e.getMessage());
        }
    }

    /**
     * Unregister with the Mediator. 
     */
    public void unregister()
        throws RemoteException
    {
        getMediator().unregister(this);
    }

    /**
     * Handle a recieved event.
     */
    public void handleEvent(MediatedEvent event)
        throws RemoteException
    {
        if (event instanceof PollEvent)
        {
            //Respond to a poll event with proof of life.
            PollEvent e = new PollEvent(this, event);
            sendEvent(e);
        }
    }

    /**
     * This instance of the service is now in charge of running the
     * thread.
     */
    public final void setAsSingleton()
        throws RemoteException
    {
        isSingleton = true;
        startRunning();
    }

    public final boolean isSingleton()
        throws RemoteException
    {
        return isSingleton;
    }

    /**
     * Send an event to the mediator.
     */
    public void sendEvent(MediatedEvent event)
        throws RemoteException
    {
        getMediator().handleEvent(event);
    }

    /**
     * Commands to start and stop.
     */
    public synchronized void startRunning()
        throws RemoteException
    {
        if (isSingleton())
        {
            try
            {
                taskRunner = new TaskRunner(logFile);
                taskRunner.start();
            }
            catch (Exception e)
            {
                Log.error(e);
                throw new RemoteException(SERVICE_NAME +
                                          ": Couldn't create or start thread: "
                                          + e.getMessage());
            }        

            // Make sure thread stays alive at least START_TIME milliseconds.
            try
            {
                Thread.sleep(START_TIME);
            }
            catch (InterruptedException awaken)
            {
            }
            if (!isRunning())
            {
                throw new RemoteException
                    ("TaskRunner thread died as soon as it was started!");
            }
        }
        else
        {
            getSingleton().startRunning();
        }
    }

    public final void stopRunning()
        throws RemoteException
    {
        if (isSingleton())
        {
            if (taskRunner != null)
            {
                taskRunner.sendStopSignal();
                
                // Make sure the task runner actually stops within STOP_TIME
                // milliseconds.
                long timer = System.currentTimeMillis();
                while (System.currentTimeMillis() - timer <= STOP_TIME)
                {
                    if (!isRunning())
d148 7
a154 1
                    try
d156 21
a176 1
                        Thread.sleep(1000);
d178 2
a179 1
                    catch (InterruptedException awaken)
d181 8
d191 11
a201 5
                if (isRunning())
                {
                    throw new RemoteException
                        ("TaskRunner thread didn't respond to die command!");
                }
a203 4
        else
        {
            getSingleton().stopRunning();
        }
d207 1
a207 1
     * Checks whether this cluster has a live task runner thread.
d209 1
a209 2
    public final boolean isRunning()
        throws RemoteException
d211 35
a245 8
        boolean running = false;
        if (isSingleton())
        {
            running = (taskRunner == null ? false : taskRunner.isAlive());
        }
        else
        {            
            running = getSingleton().isRunning();
a246 2
        return running;
    }
d248 2
a249 11
    /**
     * Shuts down this service, stopping the task running thread.
     */
    public final void shutdown()
    {
        setInit(false);
        try
        {
            unregister();
        }
        catch (Exception e)
d251 5
a255 13
            Log.error(SERVICE_NAME + ": Task runner shutdown failed", e);
        }

    }

    /**
     * Macro to retrieve the cluster's mediator.
     */
    private final TaskRunnerMediatorSpec getMediator()
        throws RemoteException
    {
        return (TaskRunnerMediatorSpec) ClusterObject.get
            (TaskRunnerMediator.CLUSTER_KEY);
a257 8
    /**
     * Macro to retrieve the cluster's singleton.
     */
    private final TaskRunnerServiceSpec getSingleton()
        throws RemoteException
    {
        return (TaskRunnerServiceSpec) getMediator().getSingleton();
    }
@


1.23
log
@SequencedHashtable, BufferCache, and BaseUnicastRemoteService have been moved into Turbine.  Changed references accordingly.
@
text
@d65 1
a65 1
 * @@version $Id: TaskRunnerService.java,v 1.22 2001/04/12 19:10:15 dlr Exp $
d98 12
@


1.22
log
@Remove unnecessary import.
@
text
@a57 1
import org.tigris.helm.tool.rmi.BaseUnicastRemoteService;
d65 1
a65 1
 * @@version $Id: TaskRunnerService.java,v 1.21 2001/04/12 19:09:59 dlr Exp $
@


1.21
log
@Pushed base Turbine Service implementation into BaseUnicastRemoteService.
@
text
@a54 1
//import org.apache.turbine.services.resources.*;
d66 1
a66 1
 * @@version $Id: TaskRunnerService.java,v 1.20 2001/04/12 00:43:31 leonardr Exp $
@


1.20
log
@Wrong word.
@
text
@a51 1
import java.rmi.server.UnicastRemoteObject;
d55 1
a55 1
import org.apache.turbine.services.resources.*;
d59 1
d62 2
a63 2
 * Starts up and controls Helm's <code>TaskRunner</code> thread.  Can
 * be manually controlled by <code>AdminUtils</code>.
d67 1
a67 1
 * @@version $Id: TaskRunnerService.java,v 1.19 2001/04/11 23:54:33 leonardr Exp $
d69 2
a70 2
public class TaskRunnerService extends UnicastRemoteObject
    implements TaskRunnerServiceSpec, Service
a100 6
    private boolean isInitialized;
    private InitableBroker initableBroker;
    private String name;
    private Properties properties;
    private ServiceBroker serviceBroker;

a104 6

        isInitialized = false;
        initableBroker = null;
        properties = null;
        name = null;
        serviceBroker = null;
d315 3
d325 3
a331 67
    }

    // Turbine Service interface

    public void setInitableBroker( InitableBroker broker )
    {
        this.initableBroker = broker;
    }

    public InitableBroker getInitableBroker()
    {
        return initableBroker;
    }

    public void init(Object data)
        throws InitializationException
    {
        init((ServletConfig) data);
    }

    public void init() throws InitializationException
    {
        // No late initialization to do.
    }

    protected void setInit(boolean value)
    {
        this.isInitialized = value;
    }
    
    public boolean getInit()
    {
        return isInitialized;
    }

    public Properties getProperties()
    {
        if (name == null)
        {
            return null;
        }

        if (properties == null)
        {
            properties = getServiceBroker().getProperties(name);
        }
        return properties;
    }

    public void setName(String name)
    {
        this.name = name;
    }

    public String setName()
    {
        return name;
    }

    public ServiceBroker getServiceBroker()
    {
        return serviceBroker;
    }

    public void setServiceBroker(ServiceBroker broker)
    {
        this.serviceBroker = broker;
@


1.19
log
@Removed debug.
@
text
@d67 1
a67 1
 * @@version $Id: TaskRunnerService.java,v 1.18 2001/04/11 23:47:56 dlr Exp $
d322 1
a322 1
            Log.error(SERVICE_NAME + ": Task runner startup failed", e);
@


1.18
log
@Removed TaskRunner from interface.  Now delegating to it internally.
@
text
@d67 1
a67 1
 * @@version $Id: TaskRunnerService.java,v 1.17 2001/04/11 23:38:45 leonardr Exp $
a301 1
            Log.debug("The singleton's taskRunner.isAlive() returns " + running);
@


1.17
log
@Don't get references to the singleton's objects; if you're not the singleton, find the singleton, and tell them to do whatever you want to do.
@
text
@d67 1
a67 1
 * @@version $Id: TaskRunnerService.java,v 1.16 2001/04/11 22:43:17 dlr Exp $
d99 2
d110 2
d190 1
a190 1
    public void setAsSingleton()
d193 1
d197 6
d228 2
a229 2
                throw new RemoteException(SERVICE_NAME
                                          + ": Couldn't create or start thread: "
@


1.16
log
@Catch Exception (instead of Throwable to miss Errors), and log stack
traces to the Turbine log file.
@
text
@d67 1
a67 1
 * @@version $Id: TaskRunnerService.java,v 1.15 2001/04/11 22:19:42 dlr Exp $
d134 1
a138 12
    public TaskRunner getTaskRunner()
        throws RemoteException
    {
        return taskRunner;
    }

    public void setTaskRunner(TaskRunner taskRunner)
        throws RemoteException
    {
        this.taskRunner = taskRunner;
    }

d207 1
a207 1
        try
d209 12
a220 17
            // HELP: Can't get a reference to ourself, because the instace
            // supplied by the mediator is a TaskRunnerService_Stub.
            TaskRunnerServiceSpec singleton = getSingleton();
            singleton.setTaskRunner(new TaskRunner(logFile));
            Log.debug(SERVICE_NAME + ".startRunning(): " + 
                      "getSingleton().taskRunner=" +
                      getSingleton().getTaskRunner());
            Log.debug(SERVICE_NAME + ".startRunning(): this.taskRunner=" +
                      this.taskRunner);
            singleton.getTaskRunner().start();
        }
        catch (Exception e)
        {
            Log.error(e);
            throw new RemoteException(SERVICE_NAME + ": Couldn't create or " +
                                      "start thread: " + e.getMessage());
        }
d222 13
a234 7
        // Make sure thread stays alive at least START_TIME milliseconds.
        try
        {
            Thread.sleep(START_TIME);
        }
        catch (InterruptedException awaken)
        {
d236 1
a236 1
        if (!isRunning())
d238 1
a238 2
            throw new RemoteException
                ("TaskRunner thread died as soon as it was started!");        
d245 1
a245 2
        TaskRunner thread = getSingleton().getTaskRunner();
        if (thread != null)
d247 1
a247 6
            thread.sendStopSignal();

            // Make sure the task runner actually stops within STOP_TIME
            // milliseconds.
            long timer = System.currentTimeMillis();
            while (System.currentTimeMillis() - timer <= STOP_TIME)
d249 6
a254 1
                if (!isRunning())
d256 11
a266 1
                    break;
d268 1
a268 5
                try
                {
                    Thread.sleep(1000);
                }
                catch (InterruptedException awaken)
d270 2
d274 4
a277 5
            if (isRunning())
            {
                throw new RemoteException
                    ("TaskRunner thread didn't respond to die command!");
            }
d287 11
a297 5
        TaskRunner taskRunner = getSingleton().getTaskRunner();
        Log.debug("isRunning(): getSingleton()=" + taskRunner);
        Log.debug("isRunning(): getSingleton().isAlive()=" +
                  taskRunner.isAlive());
        return (taskRunner == null ? false : taskRunner.isAlive());
@


1.15
log
@exportObject(this) is done by UnicastRemoteObject's constructor.
@
text
@d67 1
a67 1
 * @@version $Id: TaskRunnerService.java,v 1.14 2001/04/11 21:53:15 dlr Exp $
d157 11
a167 2
        Log.debug(SERVICE_NAME + ": Attempting registration with mediator");
        getMediator().register(this);
d231 1
a231 1
        catch (Throwable t)
d233 1
a233 1
            t.printStackTrace();
d235 1
a235 1
                                      "start thread: " + t.getMessage());
@


1.14
log
@* Implemented Turbine's Service interface, since it appears we may
have to extend UnicastRemoteObject.

* Lowered wait times.

* Added to TaskRunner member JavaDoc.

* Corrected init(ServletConfig) impl. to do things in the right order.

* Implemented new TaskRunnerServiceSpec Remote interface.

* register() is a bit fishy...haven't gotten registration to spread
its wings and fly.

* Added debug trace to startRunning() stopRunning() and revamped them
a bit.

* Return the proper Remote interface for getMediator() and
getSingleton().
@
text
@d67 1
a67 1
 * @@version $Id: $
d158 1
a158 2
        getMediator().register((ClusteredSingletonColleague)
                               UnicastRemoteObject.exportObject(this));
@


1.13
log
@* Used getMediator().

* Used TaskRunnerMediator's CLUSTER_KEY.
@
text
@d51 2
a52 1
import java.rmi.*;
d67 4
a70 3
 * @@version $Id: TaskRunnerService.java,v 1.12 2001/04/06 20:51:22 dlr Exp $ */
public class TaskRunnerService extends TurbineBaseService 
    implements ClusteredSingletonColleague
d80 1
a80 1
    private static final long STOP_TIME=5000;
d86 1
a86 1
    private static final long START_TIME=5000;
d89 2
a90 1
     * The thread which runs batches of tasks for this service.
d99 16
d121 1
d123 2
d128 1
d132 3
a134 1
            Log.error("TaskRunnerService registration with mediator failed");
a135 3
        Properties props = getProperties();
        logFile = props.getProperty("logFile");
        taskRunner = new TaskRunner(logFile);
d138 11
a148 1
    //Implementation of the ClusteredSingletonColleage interface.
d157 3
a159 1
        getMediator().register(this);
d207 1
a207 1
    public final void startRunning()
d210 19
a228 3
        TaskRunnerService singleton = getSingleton();
        singleton.taskRunner = new TaskRunner(logFile);
        singleton.taskRunner.start();
d230 1
a230 2
        /*//Make sure it stays alive at least START_TIME
        //milliseconds.
d235 1
a235 1
        catch (InterruptedException ignore)
d238 1
a238 1
        if (!taskRunner.isRunning())
d240 1
a240 1
            throw new Exception
a242 1
        */
d248 4
a251 1
        getSingleton().taskRunner.sendStopSignal();
d253 18
a270 5
        /*//Make sure the task runner actually stops
        //within STOP_TIME milliseconds.
        while (newSeconds-seconds <= STOP_TIME)
        {
            if (!isRunning())
d272 2
a273 1
                break;
a274 2
            newSeconds = System.currentTimeMillis();
            Thread.sleep(1000);
a275 5
        if (isRunning())
        {
            throw new Exception
                ("TaskRunner thread didn't respond to die command!");
                }*/                              
d278 3
d284 5
a288 1
        return getSingleton().taskRunner.isAlive();
d308 1
a308 1
    private final TaskRunnerMediator getMediator()
d311 1
a311 1
        return (TaskRunnerMediator) ClusterObject.get
d315 1
a315 1
    private final TaskRunnerService getSingleton()
d318 68
a385 1
        return (TaskRunnerService) getMediator().getSingleton();
@


1.12
log
@Information more easily parsable by someone not familiar with the API.
@
text
@d66 1
a66 1
 * @@version $Id: TaskRunnerService.java,v 1.11 2001/04/06 20:40:22 leonardr Exp $ */
a75 6
     * RMI URL fragment to the mediator.
     */
    public static final String MEDIATOR_URL =
        "org.tigris.helm.tool.task.TaskRunnerMediator";

    /**
d134 1
a134 3
        TaskRunnerMediator mediator =
            (TaskRunnerMediator)ClusterObject.get(MEDIATOR_URL);
        mediator.unregister(this);
d246 2
a247 1
        return (TaskRunnerMediator) ClusterObject.get(MEDIATOR_URL);
@


1.11
log
@Fixed compile errors.
@
text
@d66 1
a66 1
 * @@version $Id: TaskRunnerService.java,v 1.10 2001/04/06 20:32:26 dlr Exp $ */
d115 1
a115 1
            Log.error("TaskRunnerService mediator registration failed");
@


1.10
log
@* Broke long line.

* Added and made use of getMediator() and getSingleton() macros.
@
text
@d66 1
a66 1
 * @@version $Id: TaskRunnerService.java,v 1.9 2001/04/06 20:27:42 leonardr Exp $ */
d151 1
a151 5
        if (event instanceof SingletonRecognitionEvent)
        {
            startRunning();
        }
        else if (event instanceof PollEvent)
d160 10
d252 1
d258 1
@


1.9
log
@Added unregister method to interface.
@
text
@d66 1
a66 1
 * @@version $Id: TaskRunnerService.java,v 1.8 2001/04/06 20:12:59 dlr Exp $ */
d78 2
a79 1
    public static final String MEDIATOR_URL = "org.tigris.helm.tool.task.TaskRunnerMediator";
d131 1
a131 3
        TaskRunnerMediator mediator =
            (TaskRunnerMediator)ClusterObject.get(MEDIATOR_URL);
        mediator.register(this);
d169 1
a169 2
        TaskRunnerMediator mediator = (TaskRunnerMediator)ClusterObject.get(MEDIATOR_URL);
        mediator.handleEvent(event);
d178 1
a178 3
        TaskRunnerMediator mediator = (TaskRunnerMediator)ClusterObject.get(MEDIATOR_URL);
        TaskRunnerService singleton = (TaskRunnerService)
            mediator.getSingleton();
d202 1
a202 4
        TaskRunnerMediator mediator = (TaskRunnerMediator)ClusterObject.get(MEDIATOR_URL);
        TaskRunnerService singleton = (TaskRunnerService)
            mediator.getSingleton();
        singleton.taskRunner.sendStopSignal();
d225 1
a225 4
        TaskRunnerMediator mediator = (TaskRunnerMediator)ClusterObject.get(MEDIATOR_URL);
        TaskRunnerService singleton = (TaskRunnerService)
            mediator.getSingleton();
        return singleton.taskRunner.isAlive();
d243 10
@


1.8
log
@Provide a useful error message.
@
text
@d66 1
a66 1
 * @@version $Id: TaskRunnerService.java,v 1.7 2001/04/06 20:05:29 leonardr Exp $ */
d136 11
d246 1
a246 1
            stopRunning();
@


1.7
log
@Implemented TaskRunnerService as a ClusteredSingletonMediator.
@
text
@d66 1
a66 1
 * @@version $Id: TaskRunnerService.java,v 1.6 2001/03/26 18:33:55 leonardr Exp $ */
d114 1
a114 1
            Log.error("Registration failed.");
@


1.6
log
@Moved some complexity out of the servlet and into the taskrunnerservice.
@
text
@d51 1
d58 2
d66 3
a68 2
 * @@version $Id: TaskRunnerService.java,v 1.5 2001/03/26 17:37:01 leonardr Exp $ */
public class TaskRunnerService extends TurbineBaseService
d75 4
d108 8
d118 16
d135 7
a141 2
        taskRunner = new TaskRunner(logFile);
        try
d143 1
a143 1
            taskRunner.start();
d145 1
a145 1
        catch (Exception e)
d147 3
a149 1
            Log.error(SERVICE_NAME + ": Task runner startup failed", e);
d153 13
d167 1
a167 1
        throws Exception
d169 5
a173 2
        taskRunner = new TaskRunner(logFile);
        taskRunner.start();
d175 1
a175 1
        //Make sure it stays alive at least START_TIME
d184 1
a184 2
        
        if (!isRunning())
d187 1
a187 1
                ("TaskRunner thread died as soon as it was started!");
d189 1
d193 1
a193 1
        throws Exception
d195 4
a198 1
        taskRunner.sendStopSignal();
d200 1
a200 4
        long seconds = System.currentTimeMillis();
        long newSeconds = seconds;

        //Make sure the task runner actually stops
d210 1
a210 1
        }        
d215 1
a215 1
        }
d219 1
d221 4
a224 1
        return taskRunner.isAlive();
@


1.5
log
@Couple taskrunner changes. First, start a new thread rather than trying to revive the old thread. Second, make sure the thread stops (or stays started) before reporting it as such.
@
text
@d63 1
a63 1
 * @@version $Id: TaskRunnerService.java,v 1.4 2001/03/16 23:16:55 leonardr Exp $ */
d71 12
d115 1
d118 4
d124 4
a127 1
            taskRunner.start();
d129 2
a130 1
        catch (Exception e)
d132 2
a133 1
            Log.error(SERVICE_NAME + ": Task runner startup failed", e);
d138 1
d141 20
d174 9
a182 1
        stopRunning();
@


1.4
log
@The TaskRunner writes the current time to a log every time it runs tasks. This is so the health of the thread can be monitored with Big Brother or equivalent.
@
text
@d63 1
a63 1
 * @@version $Id: TaskRunnerService.java,v 1.3 2001/03/16 17:28:14 dlr Exp $ */
d77 5
d89 1
a89 1
        String logFile = props.getProperty("logFile");
d104 9
a112 1
        taskRunner.start();
@


1.3
log
@Improved JavaDoc.
@
text
@d63 1
a63 1
 * @@version $Id: TaskRunnerService.java,v 1.2 2001/03/16 17:25:02 dlr Exp $ */
a76 9
     * Default constructor.
     */
    public TaskRunnerService()
        throws Exception
    {
        taskRunner = new TaskRunner();
    }

    /**
d83 4
@


1.2
log
@Uninitialize this puppy on shutdown.
@
text
@d63 1
a63 1
 * @@version $Id: TaskRunnerService.java,v 1.1 2001/03/14 02:35:53 dlr Exp $ */
d118 1
a118 1
     * Shuts down this service.
@


1.1
log
@Starts up and controls Helm's <code>TaskRunner</code> thread.  Can
be manually controlled by <code>AdminUtils</code>.
@
text
@d63 1
a63 1
 * @@version $Id: $ */
d122 1
@

