1 package org.apache.turbine.services.schedule;
2
3 /* ====================================================================
4 * The Apache Software License, Version 1.1
5 *
6 * Copyright (c) 2001 The Apache Software Foundation. All rights
7 * reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in
18 * the documentation and/or other materials provided with the
19 * distribution.
20 *
21 * 3. The end-user documentation included with the redistribution,
22 * if any, must include the following acknowledgment:
23 * "This product includes software developed by the
24 * Apache Software Foundation (http://www.apache.org/)."
25 * Alternately, this acknowledgment may appear in the software itself,
26 * if and wherever such third-party acknowledgments normally appear.
27 *
28 * 4. The names "Apache" and "Apache Software Foundation" and
29 * "Apache Turbine" must not be used to endorse or promote products
30 * derived from this software without prior written permission. For
31 * written permission, please contact apache@apache.org.
32 *
33 * 5. Products derived from this software may not be called "Apache",
34 * "Apache Turbine", nor may "Apache" appear in their name, without
35 * prior written permission of the Apache Software Foundation.
36 *
37 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
41 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48 * SUCH DAMAGE.
49 * ====================================================================
50 *
51 * This software consists of voluntary contributions made by many
52 * individuals on behalf of the Apache Software Foundation. For more
53 * information on the Apache Software Foundation, please see
54 * <http://www.apache.org/>.
55 */
56
57 import java.util.List;
58 import java.util.Vector;
59 import javax.servlet.ServletConfig;
60 import org.apache.torque.util.Criteria;
61 import org.apache.turbine.services.InitializationException;
62 import org.apache.turbine.services.TurbineBaseService;
63 import org.apache.turbine.services.resources.TurbineResources;
64
65 /***
66 * Service for a cron like scheduler.
67 *
68 * @author <a href="mailto:mbryson@mont.mindspring.com">Dave Bryson</a>
69 * @version $Id: TurbineSchedulerService.java,v 1.3 2002/07/11 16:53:24 mpoeschl Exp $
70 */
71 public class TurbineSchedulerService
72 extends TurbineBaseService
73 implements ScheduleService
74 {
75 /***
76 * The queue.
77 */
78 protected JobQueue scheduleQueue = null;
79
80 /***
81 * The main loop for starting jobs.
82 */
83 protected MainLoop mainLoop;
84
85 /***
86 * The thread used to process commands.
87 */
88 protected Thread thread;
89
90 /***
91 * Creates a new instance.
92 */
93 public TurbineSchedulerService()
94 {
95 mainLoop = null;
96 thread = null;
97 }
98
99 /***
100 * Called the first time the Service is used.<br>
101 *
102 * Load all the jobs from cold storage. Add jobs to the queue
103 * (sorted in ascending order by runtime) and start the scheduler
104 * thread.
105 *
106 * @param config A ServletConfig.
107 */
108 public void init(ServletConfig config)
109 throws InitializationException
110 {
111 try
112 {
113 // START SCHEDULER HERE
114 if ( TurbineResources.getBoolean("scheduler.enabled", false) )
115 {
116 scheduleQueue = new JobQueue();
117 mainLoop = new MainLoop();
118
119 // Load all from cold storage.
120 List jobs = JobEntryPeer.doSelect(new Criteria());
121
122 if ( jobs != null && jobs.size() > 0 )
123 {
124 scheduleQueue.batchLoad(jobs);
125 restart();
126 }
127
128 setInit(true);
129 }
130 else
131 {
132 org.apache.turbine.util.Log.info ("TurbineSchedulerService was not started " +
133 "because scheduler.enabled is not 'true' in the TurbineResources.properties file.");
134 }
135 }
136 catch (Exception e)
137 {
138 throw new InitializationException("TurbineSchedulerService failed to initialize", e);
139 }
140 }
141
142 /***
143 * Shutdowns the service.
144 *
145 * This methods interrupts the housekeeping thread.
146 */
147 public void shutdown()
148 {
149 if(getThread() != null)
150 {
151 getThread().interrupt();
152 }
153 }
154
155 /***
156 * Get a specific Job from Storage.
157 *
158 * @param oid The int id for the job.
159 * @return A JobEntry.
160 * @exception Exception, a generic exception.
161 */
162 public JobEntry getJob(int oid)
163 throws Exception
164 {
165 JobEntry je = JobEntryPeer.getJob(oid);
166 return scheduleQueue.getJob(je);
167 }
168
169 /***
170 * Add a new job to the queue.
171 *
172 * @param je A JobEntry with the job to add.
173 * @exception Exception, a generic exception.
174 */
175 public void addJob(JobEntry je)
176 throws Exception
177 {
178 try
179 {
180 // Save to DB.
181 je.save();
182 }
183 catch(Exception e)
184 {
185 // Log problems.
186 org.apache.turbine.util.Log.error ( "Problem saving new Scheduled Job: " + e);
187 }
188 // Add to the queue.
189 scheduleQueue.add(je);
190 restart();
191 }
192
193 /***
194 * Remove a job from the queue.
195 *
196 * @param je A JobEntry with the job to remove.
197 * @exception Exception, a generic exception.
198 */
199 public void removeJob(JobEntry je)
200 throws Exception
201 {
202 // First remove from DB.
203 try
204 {
205 Criteria c = new Criteria()
206 .add(JobEntryPeer.OID, je.getPrimaryKey());
207
208 JobEntryPeer.doDelete(c);
209 }
210 catch(Exception ouch)
211 {
212 // Log problem.
213 org.apache.turbine.util.Log.error ( "Problem removing Scheduled Job: " + ouch);
214 }
215
216 // Remove from the queue.
217 scheduleQueue.remove(je);
218 restart();
219 }
220
221 /***
222 * Modify a Job.
223 *
224 * @param je A JobEntry with the job to modify
225 * @exception Exception, a generic exception.
226 */
227 public void updateJob(JobEntry je)
228 throws Exception
229 {
230 try
231 {
232 je.calcRunTime();
233 je.save();
234 }
235 catch(Exception e)
236 {
237 // Log problems.
238 org.apache.turbine.util.Log.error ( "Problem updating Scheduled Job: " + e);
239 }
240 // Update the queue.
241 scheduleQueue.modify(je);
242 restart();
243 }
244
245 /***
246 * List jobs in the queue. This is used by the scheduler UI.
247 *
248 * @return A Vector of jobs.
249 */
250 public Vector listJobs()
251 {
252 return scheduleQueue.list();
253 }
254
255 /***
256 * Return the thread being used to process commands, or null if
257 * there is no such thread. You can use this to invoke any
258 * special methods on the thread, for example, to interrupt it.
259 *
260 * @return A Thread.
261 */
262 public synchronized Thread getThread()
263 {
264 return thread;
265 }
266
267 /***
268 * Set thread to null to indicate termination.
269 */
270 private synchronized void clearThread()
271 {
272 thread = null;
273 }
274
275 /***
276 * Start (or restart) a thread to process commands, or wake up an
277 * existing thread if one is already running. This method can be
278 * invoked if the background thread crashed due to an
279 * unrecoverable exception in an executed command.
280 */
281 public synchronized void restart()
282 {
283 if (thread == null)
284 {
285 // Create the the housekeeping thread of the scheduler. It will wait
286 // for the time when the next task needs to be started, and then
287 // launch a worker thread to execute the task.
288 thread = new Thread(mainLoop, ScheduleService.SERVICE_NAME);
289 // Indicate that this is a system thread. JVM will quit only when there
290 // are no more active user threads. Settings threads spawned internally
291 // by Turbine as daemons allows commandline applications using Turbine
292 // to terminate in an orderly manner.
293 thread.setDaemon(true);
294 thread.start();
295 }
296 else
297 {
298 notify();
299 }
300 }
301
302 /***
303 * Return the next Job to execute, or null if thread is
304 * interrupted.
305 *
306 * @return A JobEntry.
307 * @exception Exception, a generic exception.
308 */
309 private synchronized JobEntry nextJob()
310 throws Exception
311 {
312 try
313 {
314 while ( !Thread.interrupted() )
315 {
316 // Grab the next job off the queue.
317 JobEntry je = scheduleQueue.getNext();
318
319 if (je == null)
320 {
321 // Queue must be empty. Wait on it.
322 wait();
323 }
324 else
325 {
326 long now = System.currentTimeMillis();
327 long when = je.getNextRuntime();
328
329 if ( when > now )
330 {
331 // Wait till next runtime.
332 wait(when - now);
333 }
334 else
335 {
336 // Update the next runtime for the job.
337 scheduleQueue.updateQueue(je);
338 // Return the job to run it.
339 return je;
340 }
341 }
342 }
343 }
344 catch (InterruptedException ex)
345 {
346 }
347
348 // On interrupt.
349 return null;
350 }
351
352 /***
353 * Inner class. This is isolated in its own Runnable class just
354 * so that the main class need not implement Runnable, which would
355 * allow others to directly invoke run, which is not supported.
356 */
357 protected class MainLoop
358 implements Runnable
359 {
360 /***
361 * Method to run the class.
362 */
363 public void run()
364 {
365 try
366 {
367 for(;;)
368 {
369 JobEntry je = nextJob();
370 if ( je != null )
371 {
372 // Start the thread to run the job.
373 Runnable wt = new WorkerThread(je);
374 Thread helper = new Thread(wt);
375 helper.start();
376 }
377 else
378 {
379 break;
380 }
381 }
382 }
383 catch(Exception e)
384 {
385 // Log error.
386 org.apache.turbine.util.Log.error ( "Error running a Scheduled Job: " + e);
387 }
388 finally
389 {
390 clearThread();
391 }
392 }
393 }
394 }
This page was automatically generated by Maven