/*==========================================================================*\ | $Id: ManagedJobBase.java,v 1.2 2010/09/27 00:30:22 stedwar2 Exp $ |*-------------------------------------------------------------------------*| | Copyright (C) 2008-2009 Virginia Tech | | This file is part of Web-CAT. | | Web-CAT is free software; you can redistribute it and/or modify | it under the terms of the GNU Affero General Public License as published | by the Free Software Foundation; either version 3 of the License, or | (at your option) any later version. | | Web-CAT 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 Affero General Public License | along with Web-CAT; if not, see <http://www.gnu.org/licenses/>. \*==========================================================================*/ package org.webcat.jobqueue; import com.webobjects.eoaccess.*; import com.webobjects.eocontrol.*; import com.webobjects.foundation.*; import er.extensions.eof.ERXConstant; import java.util.Enumeration; import org.apache.log4j.Logger; import org.webcat.core.IndependentEOManager; // ------------------------------------------------------------------------- /** * A subclass of IndependentEOManager that holds one {@link JobBase}. This * class also provides progress management for a job; by placing these methods * on ManagedJobBase instead of {@link JobBase}, progress updates can be * persisted to the database immediately and independently of other objects in * various editing contexts. * * @author Stephen Edwards * @author Last changed by $Author: stedwar2 $ * @version $Revision: 1.2 $, $Date: 2010/09/27 00:30:22 $ */ public abstract class ManagedJobBase extends IndependentEOManager { //~ Constructors .......................................................... // ---------------------------------------------------------- /** * Creates a new object. * @param job The job to wrap */ public ManagedJobBase(JobBase job) { super(job); } //~ Methods ............................................................... // ---------------------------------------------------------- /** * Retrieve this object's <code>enqueueTime</code> value. * @return the value of the attribute */ public NSTimestamp enqueueTime() { return (NSTimestamp)valueForKey(JobBase.ENQUEUE_TIME_KEY); } // ---------------------------------------------------------- /** * Change the value of this object's <code>enqueueTime</code> * property. * * @param value The new value for this property */ public void setEnqueueTime( NSTimestamp value ) { takeValueForKey(value, JobBase.ENQUEUE_TIME_KEY); } // ---------------------------------------------------------- /** * Retrieve this object's <code>isCancelled</code> value. * @return the value of the attribute */ public boolean isCancelled() { return (Boolean)valueForKey(JobBase.IS_CANCELLED_KEY); } // ---------------------------------------------------------- /** * Change the value of this object's <code>isCancelled</code> * property. * * @param value The new value for this property */ public void setIsCancelled( boolean value ) { takeValueForKey(value, JobBase.IS_CANCELLED_KEY); } // ---------------------------------------------------------- /** * Retrieve this object's <code>isReady</code> value. * @return the value of the attribute */ public boolean isReady() { return (Boolean)valueForKey(JobBase.IS_READY_KEY); } // ---------------------------------------------------------- /** * Change the value of this object's <code>isReady</code> * property. * * @param value The new value for this property */ public void setIsReady( boolean value ) { takeValueForKey(value, JobBase.IS_READY_KEY); } // ---------------------------------------------------------- /** * Retrieve this object's <code>priority</code> value. * @return the value of the attribute */ public int priority() { Number result = (Number)valueForKey(JobBase.PRIORITY_KEY); return (result == null) ? 0 : result.intValue(); } // ---------------------------------------------------------- /** * Change the value of this object's <code>priority</code> * property. * * @param value The new value for this property */ public void setPriority(int value) { takeValueForKey( ERXConstant.integerForInt(value), JobBase.PRIORITY_KEY); } // ---------------------------------------------------------- /** * Retrieve this object's <code>progress</code> value. * @return the value of the attribute */ public double progress() { Number result = (Number)valueForKey(JobBase.PROGRESS_KEY); return (result == null) ? 0 : result.doubleValue(); } // ---------------------------------------------------------- /** * Change the value of this object's <code>progress</code> * property. * * @param value The new value for this property */ public void setProgress(double value) { takeValueForKey(Double.valueOf(value), JobBase.PROGRESS_KEY); } // ---------------------------------------------------------- /** * Retrieve this object's <code>progressMessage</code> value. * @return the value of the attribute */ public String progressMessage() { return (String)valueForKey(JobBase.PROGRESS_MESSAGE_KEY); } // ---------------------------------------------------------- /** * Change the value of this object's <code>progressMessage</code> * property. * * @param value The new value for this property */ public void setProgressMessage(String value) { takeValueForKey(value, JobBase.PROGRESS_MESSAGE_KEY); } // ---------------------------------------------------------- /** * Retrieve this object's <code>scheduledTime</code> value. * @return the value of the attribute */ public NSTimestamp scheduledTime() { return (NSTimestamp)valueForKey(JobBase.SCHEDULED_TIME_KEY); } // ---------------------------------------------------------- /** * Change the value of this object's <code>scheduledTime</code> * property. * * @param value The new value for this property */ public void setScheduledTime(NSTimestamp value) { takeValueForKey(value, JobBase.SCHEDULED_TIME_KEY); } // ---------------------------------------------------------- /** * Retrieve the value of the <code>suspensionReason</code> attribute. * * @return the value of the attribute */ public String suspensionReason() { return (String) valueForKey(JobBase.SUSPENSION_REASON_KEY); } // ---------------------------------------------------------- /** * Set the value of the <code>suspensionReason</code> attribute. * * @param value The new value of the attribute */ public void setSuspensionReason(String value) { takeValueForKey(value, JobBase.SUSPENSION_REASON_KEY); } // ---------------------------------------------------------- /** * Retrieve the entity pointed to by the <code>user</code> * relationship. * @return the entity in the relationship */ public org.webcat.core.User user() { return (org.webcat.core.User)valueForKey(JobBase.USER_KEY); } // ---------------------------------------------------------- /** * Set the entity pointed to by the <code>user</code> * relationship. This method is a type-safe version of * <code>addObjectToBothSidesOfRelationshipWithKey()</code>. * * @param value The new entity to relate to */ public void setUserRelationship(org.webcat.core.User value) { addObjectToBothSidesOfRelationshipWithKey(value, JobBase.USER_KEY); } // ---------------------------------------------------------- /** * Retrieve the entity pointed to by the <code>worker</code> * relationship. * @return the entity in the relationship */ public WorkerDescriptor worker() { return (WorkerDescriptor)valueForKey(JobBase.WORKER_KEY); } // ---------------------------------------------------------- /** * Set the entity pointed to by the <code>worker</code> * relationship. This method is a type-safe version of * <code>addObjectToBothSidesOfRelationshipWithKey()</code>. * * @param value The new entity to relate to */ public void setWorkerRelationship(WorkerDescriptor value) { addObjectToBothSidesOfRelationshipWithKey(value, JobBase.WORKER_KEY); } // ---------------------------------------------------------- /** * Begins a task or subtask for progress monitoring. * * @param taskName a description of the task that will be stored in the * <code>progressMessage</code> attribute of the job * @param work the amount of work to be done for this task */ public void beginTask(String taskName, int work) { if (progress == null) { progress = new HierarchicalProgressTracker(); } progress.beginTask(taskName, work); setProgressMessage(progress.descriptionOfCurrentTask()); saveProgress(); } // ---------------------------------------------------------- /** * Begins a task or subtask for progress monitoring. * * @param taskName a description of the task that will be stored in the * <code>progressMessage</code> attribute of the job * @param weights an array of integer weights that determine how each of * the subtasks of this task will be weighted in the progress * calculation */ public void beginTask(String taskName, int[] weights) { if (progress == null) { progress = new HierarchicalProgressTracker(); } progress.beginTask(taskName, weights); setProgressMessage(progress.descriptionOfCurrentTask()); saveProgress(); } // ---------------------------------------------------------- /** * Notifies the job that <code>delta</code> units of work have been * performed in the current task. Calls can be made rapidly to this method; * it is self-throttling so that the database is only updated every few * seconds to prevent performance deficiencies. * * @param delta the number of units of work completed */ public void worked(int delta) { progress.worked(delta); saveProgress(); } // ---------------------------------------------------------- /** * Notifies the current task that its work is completed. Future calls to * {@link #worked(int)} will apply to the parent task. * * It is required to call this method explicitly when a task's work is * completed. If a task requires 5 units of work and a sequence of call * that amount to <code>worked(5)</code> are made, this does <b>not</b> * cause that task to be completed. */ public void completeCurrentTask() { progress.completeCurrentTask(); setProgressMessage(progress.descriptionOfCurrentTask()); saveProgress(); } // ---------------------------------------------------------- /** * Updates the percentage of job progress completed in the job EO, and * saves it to the database if enough time has passed since the last save. */ private void saveProgress() { setProgress(progress.percentDone()); long currentTime = System.currentTimeMillis(); if (!isCancelled() && currentTime >= timeOfLastProgressSave + PROGRESS_SAVE_DELAY) { saveChanges(); timeOfLastProgressSave = System.currentTimeMillis(); } } //~ Instance/static variables ............................................. private HierarchicalProgressTracker progress; private long timeOfLastProgressSave; private static final long PROGRESS_SAVE_DELAY = 3000; static Logger log = Logger.getLogger( JobBase.class ); }