head	1.27;
access;
symbols
	TIGRIS_1_1_0RC2:1.23
	TIGRIS_1_1_0RC1:1.23
	TIGRIS_1_1:1.23.0.4
	TIGRIS_1_0_8:1.23
	TIGRIS_1_0_8RC3:1.23
	TIGRIS_1_0_8RC2:1.23
	TIGRIS_1_0_8RC1:1.23
	TIGRIS_1_0_7:1.23
	TIGRIS_1_0_7RC3:1.23
	TIGRIS_1_0_7RC2:1.23
	TIGRIS_1_0_7RC1:1.23
	TIGRIS_1_0_6:1.23
	TIGRIS_1_0_6RC5:1.23
	TIGRIS_1_0_6RC4:1.23
	TIGRIS_1_0_6RC3:1.23
	TIGRIS_1_0_6RC2:1.23
	TIGRIS_1_0_6RC1:1.23
	TIGRIS_1_0_5:1.23
	TIGRIS_1_0_5RC6:1.23
	TIGRIS_1_0_5RC5:1.23
	TIGRIS_1_0_5RC4:1.23
	TIGRIS_1_0_5RC3:1.23
	TIGRIS_1_0_5RC2:1.23
	TIGRIS_1_0_5RC1:1.23
	TIGRIS_1_0_4:1.23
	TIGRIS_1_0_3:1.23
	TIGRIS_1_0_2:1.23
	TIGRIS_1_0_1:1.23
	TIGRIS_1_0:1.23.0.6
	TIGRIS_1_0_0:1.23
	TIGRIS_1_0_0_RC1:1.23.0.2
	dlr:1.1.1
	HELM_PEER_PORT_BRANCH:1.1.1.1;
locks; strict;
comment	@# @;


1.27
date	2001.05.18.21.56.26;	author leonardr;	state dead;
branches;
next	1.26;

1.26
date	2001.04.11.23.58.18;	author dlr;	state Exp;
branches;
next	1.25;

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

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

1.23
date	2001.03.24.01.57.52;	author dlr;	state Exp;
branches
	1.23.4.1
	1.23.6.1;
next	1.22;

1.22
date	2001.03.16.23.16.55;	author leonardr;	state Exp;
branches;
next	1.21;

1.21
date	2001.03.15.19.18.18;	author leonardr;	state Exp;
branches;
next	1.20;

1.20
date	2001.03.14.02.36.26;	author dlr;	state Exp;
branches;
next	1.19;

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

1.18
date	2001.03.13.19.08.01;	author leonardr;	state Exp;
branches;
next	1.17;

1.17
date	2001.03.12.21.33.15;	author dlr;	state Exp;
branches;
next	1.16;

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

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

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

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

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

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

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

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

1.8
date	2001.03.12.18.21.00;	author leonardr;	state Exp;
branches;
next	1.7;

1.7
date	2001.03.07.01.53.28;	author lucas;	state Exp;
branches;
next	1.6;

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

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

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

1.3
date	2001.02.21.16.21.59;	author edk;	state Exp;
branches;
next	1.2;

1.2
date	2001.02.21.03.02.30;	author edk;	state Exp;
branches;
next	1.1;

1.1
date	2001.02.15.16.23.42;	author leonardr;	state dead;
branches
	1.1.1.1
	1.1.2.1;
next	;

1.1.1.1
date	2001.02.21.00.35.39;	author dlr;	state Exp;
branches;
next	;

1.1.2.1
date	2001.02.15.16.23.42;	author leonardr;	state Exp;
branches;
next	1.1.2.2;

1.1.2.2
date	2001.02.15.20.50.46;	author leonardr;	state Exp;
branches;
next	1.1.2.3;

1.1.2.3
date	2001.02.16.00.52.13;	author leonardr;	state Exp;
branches;
next	;

1.23.4.1
date	2001.08.24.22.25.52;	author leonardr;	state Exp;
branches;
next	;

1.23.6.1
date	2001.08.24.22.13.57;	author leonardr;	state Exp;
branches;
next	;


desc
@@


1.27
log
@Fixed up cluster singleton interface and made the task runner into a cluster singleton.
@
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 java.io.FileWriter;
import java.io.IOException;

import org.apache.turbine.util.Log;

import org.tigris.helm.om.Task;
import org.tigris.helm.tool.HelmEmailer;

/**
 * Runs tasks until there are no more, then sleeps until more are queued.
 * <p>
 * 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>.
 *
 * <p>Access to the program is synchronized, so only one access at a
 * time. Hopefully this will prevent data corruption. 
 *
 * @@author <a href="mailto:leonardr@@collab.net">Leonard Richardson</a>
 * @@author <a href="mailto:dlr@@collab.net">Daniel Rall</a>
 * @@version $Id: TaskRunner.java,v 1.26 2001/04/11 23:58:18 dlr Exp $
 */
class TaskRunner extends Thread
{
    /**
     * The amount of time to wait in between polling the database for another
     * batch of tasks to run.
     */
    private static final long TASK_POLL_WAIT_TIME = 5000;

    /**
     * Whether or not to print debugging information.
     */
    private static final boolean DEBUG = false;

    /**
     * Variable checked on every loop to see whether or not the thread
     * should exit.  
     */
    private volatile boolean stopNow;

    /**
     * The name of the log file to use to record this thread's heartbeat.
     */
    private String logFile;

    /**
     * Start a new TaskRunner.
     */
    public TaskRunner(String logFile)
    {
        super("Helm Task Runner");
        this.logFile = logFile;
    }

    /**
     * Tells a TaskRunner thread that it should stop running.
     */
    protected void sendStopSignal()
    {
        stopNow = true;
    }
    
    /**
     * The loop.
     */
    public void run()
    {
        stopNow = false;

        List tasksToRun = null;
        while (!stopNow)
        {
            //Overwrite the log file with the current time in seconds.
            //This is so the health of the TaskRunner can be monitored
            //with Big Brother or equivalent.
            long seconds = System.currentTimeMillis();
            writeToLog(String.valueOf(seconds));

            try 
            {            
                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 (stopNow) break;
                            Task t = (Task)i.next();

                            //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;
                                    }
                                }
                            }

                            if (DEBUG)
                            {
                                Log.debug("Running task " + t.getTaskId() + 
                                          ": " + t.getComponent() + "::" + 
                                          t.getCommand());
                            }
                            Task.runTask(t);
                            if (stopNow)
                            {
                                Log.debug("Interrupting task running because "
                                          + "thread has been stopped.");
                                break;
                            }
                        }
                    } 
                    catch (TaskException e) 
                    {
                        //Send email to the host admin(s).
                        String subject = "Update script failed.";
                        String body = 
                            "Execution of the following task failed:\n\n"
                            + e.getMessage();
                        
                        HelmEmailer emailer = new HelmEmailer();
                        emailer.sendError(subject, body);
                    }
                }
            } 
            catch (Exception e) 
            {
                Log.error("Exception thrown while running tasks" , e);
            }
    
            try 
            {
                sleep(TASK_POLL_WAIT_TIME);
            } 
            catch (InterruptedException resumeRunning)
            {
                // The JVM wants us to get back to work.
            }
        }
        writeToLog("Stopped.");
    }

    /**
     * Logs a string to the heartbeat logfile. The logfile only ever
     * has one line in it; either "Stopped" or a number representing
     * milliseconds since 1970 that the loop was last initialized.  
     */
    private void writeToLog(String s)
    {
        try 
        {
            FileWriter f = new FileWriter(logFile, false);
            f.write(s, 0, s.length());
            f.flush();
            f.close();
        }
        catch (IOException e)
        {
            Log.error("Unable to log time to file " + logFile
                      + " for write.");
        }
    }

    /**
     * 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.26
log
@This should no longer be Serializable--we don't ship it over the wire
any more.  It's controlled by the the service, which we ship the
Remote interface of over the wire.
@
text
@d70 1
a70 1
 * @@version $Id: TaskRunner.java,v 1.25 2001/04/11 23:47:27 leonardr Exp $
@


1.25
log
@Should only be called from the Service.
@
text
@a49 1
import java.io.Serializable;
d70 1
a70 1
 * @@version $Id: TaskRunner.java,v 1.24 2001/04/11 09:07:32 dlr Exp $
d72 1
a72 1
class TaskRunner extends Thread implements Serializable
@


1.24
log
@Implement Serializable for transport over the wire via RMI.
@
text
@d71 1
a71 1
 * @@version $Id: TaskRunner.java,v 1.23 2001/03/24 01:57:52 dlr Exp $
d109 1
a109 1
    public void sendStopSignal()
@


1.23
log
@Set stopNow to false immediately.
@
text
@d50 1
d71 1
a71 1
 * @@version $Id: TaskRunner.java,v 1.22 2001/03/16 23:16:55 leonardr Exp $
d73 1
a73 1
class TaskRunner extends Thread
d185 2
a186 1
                                Log.debug("Interrupting task running because thread has been stopped.");
@


1.23.4.1
log
@Committed to the branch which isn't frozen. :)
@
text
@d70 1
a70 1
 * @@version $Id: TaskRunner.java,v 1.23 2001/03/24 01:57:52 dlr Exp $
a190 1
                        Log.error("Task failed", e);
@


1.23.6.1
log
@Backported mandatory failure logging from HEAD.
@
text
@d70 1
a70 1
 * @@version $Id: TaskRunner.java,v 1.23 2001/03/24 01:57:52 dlr Exp $
a190 1
                        Log.error("Task failed", e);
@


1.22
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
@d70 1
a70 1
 * @@version $Id: TaskRunner.java,v 1.21 2001/03/15 19:18:18 leonardr Exp $
d117 3
a119 1
    {        
a120 1
        stopNow = false;
@


1.21
log
@Turned off debugging.
@
text
@d51 2
d70 1
a70 1
 * @@version $Id: TaskRunner.java,v 1.20 2001/03/14 02:36:26 dlr Exp $
d92 5
d99 1
a99 1
    public TaskRunner()
d102 1
d122 6
d205 1
a205 1

d215 1
d217 22
a238 1
    
@


1.20
log
@Refactored to be a slave to Helm's TaskRunnerService.
@
text
@d68 1
a68 1
 * @@version $Id: $
d81 1
a81 1
    private static final boolean DEBUG = true;
@


1.19
log
@Gated a lot of task debug information which was annoying dlr.
@
text
@a58 3
 * Started in the static initializer block of the  <code>Task</code> class or
 * by <code>AdminUtils</code>.  Stopped by <code>AdminUtils</code> or the
 * sandbox going down.
d65 4
d70 1
a70 1
public class TaskRunner extends Thread
d81 1
a81 1
    private static final boolean DEBUG=false;
a89 30
     * List containing the instances of this class. There should be at most
     * one instance at any one time.
     */
    public static List instances = new ArrayList();
    
    /**
     * Stop all the currently running threads.
     */
    public static int stopThreads()
    {
        int threads = 0;
        for (Iterator i = instances.iterator(); i.hasNext();)
        {
            TaskRunner tr = (TaskRunner)i.next();
            tr.sendStopSignal();
            threads++;
        }
        return threads;
    }

    /**
     * Returns the number of currently running task runner threads. 
     * Should always be <= 1.
     */
    public static int numberOfInstances()
    {
        return instances.size();
    }
    
    /**
a94 3
        instances.add(this);
        Log.info("Initializing TaskRunner. Current number of threads: " +
                 numberOfInstances());
d152 3
a154 1
                                    } else {
a200 3
        instances.remove(this);
        Log.info("TaskRunner shutting down. New number of threads: " 
                 + numberOfInstances());
@


1.18
log
@Added a new type of task which redoes the issue tracking of a project. This causes some unneccessary scripts to be run (since we lose the context of how the issue tracking was before a change was made), but it lets us offload the time it takes to build an IssueTrackingAccountDescriptor onto the task-runner thread so that the user doesn't see it. The immediate performance effect (in the two places that now use the task instead of making their own ITADs) is to reduce user-visible project creation time from 10 seconds to 3 seconds (YMMV).
@
text
@d78 5
d190 6
a195 1
                            Log.debug("Running task " + t.getTaskId() + ": " + t.getComponent() + "::" + t.getCommand());
d241 1
d248 4
a251 3
        //Display 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.
@


1.17
log
@Better messages.
@
text
@d151 3
a153 1
                        for (Iterator i = tasksToRun.iterator(); i.hasNext();)
d157 29
a185 1
                            Log.debug("Running task " + t.getTaskId());
@


1.16
log
@Indicate why we avoid Thread.stop().
@
text
@d159 1
a159 1
                                Log.debug("Interrupting task running because thread was stopped.");
d169 1
a169 1
                            "Execution of the following task failed: \n\n" 
@


1.15
log
@Replaced magic number with private constant.
@
text
@d62 3
@


1.14
log
@Re-adding volatile keyword on stopNow instance member.  JavaSoft
indicates that it's recommended in its description of what to use
instead of Thread.stop():

http://java.sun.com/products/jdk//1.2/docs/guide/misc/threadPrimitiveDeprecation.html

"To ensure prompt communication of the stop-request, the
variable must be volatile (or access to the variable must be
synchronized)."
@
text
@d69 6
d181 1
a181 1
                sleep(5000);
@


1.13
log
@More explicit.
@
text
@d72 1
a72 1
    private boolean stopNow;
d138 2
a139 1
                    //Run each task.                
@


1.12
log
@Better documented what should happen when an InterruptedException is
caught during sleep()'y time.
@
text
@d178 1
a178 1
                // The VM wants us to get back to work.
@


1.11
log
@The thread should have a name.
@
text
@d176 4
a179 1
            catch (InterruptedException e) { /*Do nothing.*/ }
@


1.10
log
@Added leonardr's Life of the TaskRunner.
@
text
@d109 1
@


1.9
log
@jrobbins says volatile is unneccessary.
@
text
@d58 4
a61 1
 * TaskRunner runs as a thread 
@


1.8
log
@Added JavaDoc and normalized braces.
@
text
@d69 1
a69 1
    private volatile boolean stopNow;
@


1.7
log
@Corrected regex madness for Torque upgrade.  -dlr
@
text
@d65 4
d71 4
d77 3
d92 4
d101 3
d111 3
d119 3
d135 2
a136 1
                    try {
d148 4
a151 2
                        }                        
                  } catch (TaskException e) {
d157 1
a157 1
                    
d162 3
a164 1
            } catch (Exception e) {
d167 1
d171 2
a172 3
            } catch (InterruptedException e) {
                //Do nothing.
            }
d179 3
d189 4
d218 1
@


1.6
log
@How about running the tasks in the right order.
@
text
@a54 1

@


1.5
log
@Move more stuff out of that loop.
@
text
@d114 1
a114 1
                        {
d117 1
@


1.4
log
@Moved debug line outside of loop.
@
text
@a180 7
            //Display the last set of tasks.
            if (oldTypeNumber == 1)
            {
                Log.debug(oldType);
            } else {
                Log.debug(oldType + " (" + oldTypeNumber + "x)");
            }            
d182 7
@


1.3
log
@always sleep 5 seconds after each attempt to run the tasks, as protection
against spinning in a tight loop if something is wrong.
@
text
@d187 1
a187 3
            }
            
            Log.debug("--------------------------------------");
d189 1
@


1.2
log
@adding files from the branch to the head
@
text
@d108 1
a108 1
                if (tasksToRun.isEmpty())
a109 7
                    try 
                    {
                        sleep(5000);
                    } catch (InterruptedException e) {
                        //Do nothing.
                    }
                } else { 
d137 6
@


1.1
log
@file TaskRunner.java was initially added on branch HELM_PEER_PORT_BRANCH.
@
text
@d1 193
@


1.1.1.1
log
@Replacing the HEAD with the HELM_PEER_PORT_BRANCH.
@
text
@a0 193
/* ================================================================
 * 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.turbine.util.Log;

import org.tigris.helm.om.Task;

import org.tigris.helm.tool.HelmEmailer;

/**
 * TaskRunner runs as a thread 
 *
 * <p>Access to the program is synchronized, so only one access at a
 * time. Hopefully this will prevent data corruption. 
 */
public class TaskRunner extends Thread
{
    private volatile boolean stopNow;

    public static List instances = new ArrayList();
    
    public static int stopThreads()
    {
        int threads = 0;
        for (Iterator i = instances.iterator(); i.hasNext();)
        {
            TaskRunner tr = (TaskRunner)i.next();
            tr.sendStopSignal();
            threads++;
        }
        return threads;
    }

    public static int numberOfInstances()
    {
        return instances.size();
    }
    
    public TaskRunner()
    {
        instances.add(this);
        Log.info("Initializing TaskRunner. Current number of threads: " +
                 numberOfInstances());
    }

    public void sendStopSignal()
    {
        stopNow = true;
    }
    
    public void run()
    {        
        List tasksToRun = null;
        stopNow = false;
        while (!stopNow)
        {
            try 
            {            
                tasksToRun = Task.getTasks();
                if (tasksToRun.isEmpty())
                {
                    try 
                    {
                        sleep(5000);
                    } catch (InterruptedException e) {
                        //Do nothing.
                    }
                } else { 
                    logTasks(tasksToRun);
                    //Run each task.                
                    try {
                        for (Iterator i = tasksToRun.iterator(); i.hasNext();)
                        {
                            if (stopNow) break;
                            Task t = (Task)i.next();
                            Task.runTask(t);
                            if (stopNow)
                            {
                                Log.debug("Interrupting task running because thread was stopped.");
                                break;
                            }
                        }                        
                  } catch (TaskException e) {
                        //Send email to the host admin(s).
                        String subject = "Update script failed.";
                        String body = 
                            "Execution of the following task failed: \n\n" 
                            + e.getMessage();
                    
                        HelmEmailer emailer = new HelmEmailer();
                        emailer.sendError(subject, body);
                    }
                }
            } catch (Exception e) {
                Log.error("Exception thrown while running tasks" , e);
            }
        }
        instances.remove(this);
        Log.info("TaskRunner shutting down. New number of threads: " 
                 + numberOfInstances());
    }
    
    public void logTasks(List tasks)
    {
        Log.debug("--------------------------------------");
        Log.debug("TaskRunner has tasks to perform!");
        Log.debug("Task summary for this round:");
        int oldTypeNumber = 1;
        String oldType = "";
        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.1.2.1
log
@TigrisTaskRunner is now TaskRunner.
@
text
@a0 193
/* ================================================================
 * Copyright (c) 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.turbine.util.Log;

import org.tigris.helm.om.Task;

import org.tigris.helm.tool.HelmEmailer;

/**
 * TaskRunner runs as a thread 
 *
 * <p>Access to the program is synchronized, so only one access at a
 * time. Hopefully this will prevent data corruption. 
 */
public class TaskRunner extends Thread
{
    private volatile boolean stopNow;

    public static List instances = new ArrayList();
    
    public static int stopThreads()
    {
        int threads = 0;
        for (Iterator i = instances.iterator(); i.hasNext();)
        {
            TaskRunner tr = (TaskRunner)i.next();
            tr.sendStopSignal();
            threads++;
        }
        return threads;
    }

    public static int numberOfInstances()
    {
        return instances.size();
    }
    
    public TaskRunner()
    {
        instances.add(this);
        Log.info("Initializing TaskRunner. Current number of threads: " +
                 numberOfInstances());
    }

    public void sendStopSignal()
    {
        stopNow = true;
    }
    
    public void run()
    {        
        List tasksToRun = null;
        stopNow = false;
        while (!stopNow)
        {
            try 
            {            
                tasksToRun = Task.getTasks();
                if (tasksToRun.isEmpty())
                {
                    try 
                    {
                        sleep(5000);
                    } catch (InterruptedException e) {
                        //Do nothing.
                    }
                } else { 
                    logTasks(tasksToRun);
                    //Run each task.                
                    try {
                        for (Iterator i = tasksToRun.iterator(); i.hasNext();)
                        {
                            if (stopNow) break;
                            Task t = (Task)i.next();
                            Task.runTask(t);
                            if (stopNow)
                            {
                                Log.debug("Interrupting task running because thread was stopped.");
                                break;
                            }
                        }                        
                  } catch (TaskException e) {
                        //Send email to the host admin(s).
                        String subject = "Update script failed.";
                        String body = 
                            "Execution of the following script failed: \n\n" 
                            + e.getMessage();
                    
                        HelmEmailer emailer = new HelmEmailer();
                        emailer.sendError(subject, body);
                    }
                }
            } catch (Exception e) {
                Log.info("Exception while running tasks: " , e);
            }
        }
        instances.remove(this);
        Log.info("TaskRunner shutting down. New number of threads: " 
                 + numberOfInstances());
    }
    
    public void logTasks(List tasks)
    {
        Log.debug("--------------------------------------");
        Log.debug("TaskRunner has tasks to perform!");
        Log.debug("Task summary for this round:");
        int oldTypeNumber = 1;
        String oldType = "";
        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.1.2.2
log
@Normalized copyright dates.
@
text
@d2 1
a2 1
 * Copyright (c) 2000-2001 CollabNet.  All rights reserved.
@


1.1.2.3
log
@Corrected terminology.
@
text
@d135 1
a135 1
                            "Execution of the following task failed: \n\n" 
d143 1
a143 1
                Log.error("Exception thrown while running tasks" , e);
@


