001: /*
002: * $Id: JobInvoker.java,v 1.5 2004/01/24 22:02:16 ajzeneski Exp $
003: *
004: * Copyright (c) 2001, 2002 The Open For Business Project - www.ofbiz.org
005: *
006: * Permission is hereby granted, free of charge, to any person obtaining a
007: * copy of this software and associated documentation files (the "Software"),
008: * to deal in the Software without restriction, including without limitation
009: * the rights to use, copy, modify, merge, publish, distribute, sublicense,
010: * and/or sell copies of the Software, and to permit persons to whom the
011: * Software is furnished to do so, subject to the following conditions:
012: *
013: * The above copyright notice and this permission notice shall be included
014: * in all copies or substantial portions of the Software.
015: *
016: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
017: * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
018: * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
019: * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
020: * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
021: * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
022: * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
023: *
024: */
025: package org.ofbiz.service.job;
026:
027: import java.util.Date;
028:
029: import org.ofbiz.service.config.ServiceConfigUtil;
030: import org.ofbiz.base.util.Debug;
031: import org.ofbiz.base.util.UtilDateTime;
032:
033: /**
034: * JobInvoker
035: *
036: * @author <a href="mailto:jaz@ofbiz.org">Andy Zeneski</a>
037: * @version $Revision: 1.5 $
038: * @since 2.0
039: */
040: public class JobInvoker implements Runnable {
041:
042: public static final String module = JobInvoker.class.getName();
043: public static final long THREAD_TTL = 18000000;
044: public static final int WAIT_TIME = 750;
045:
046: private JobPoller jp = null;
047: private Thread thread = null;
048: private Date created = null;
049: private String name = null;
050: private int count = 0;
051: private int wait = 0;
052:
053: private volatile boolean run = false;
054: private volatile Job currentJob = null;
055: private volatile int statusCode = 0;
056: private volatile long jobStart = 0;
057:
058: public JobInvoker(JobPoller jp) {
059: this (jp, WAIT_TIME);
060: }
061:
062: public JobInvoker(JobPoller jp, int wait) {
063: this .created = new Date();
064: this .run = true;
065: this .count = 0;
066: this .jp = jp;
067: this .wait = wait;
068:
069: // get a new thread
070: this .thread = new Thread(this );
071: this .thread.setDaemon(false);
072: this .name = this .thread.getName();
073:
074: if (Debug.verboseOn())
075: Debug.logVerbose("JobInoker: Starting Invoker Thread -- "
076: + thread.getName(), module);
077: this .thread.start();
078: }
079:
080: protected JobInvoker() {
081: }
082:
083: /**
084: * Tells the thread to stop after the next job.
085: */
086: public void stop() {
087: run = false;
088: }
089:
090: /**
091: * Wakes up this thread.
092: */
093: public void wakeUp() {
094: notifyAll();
095: }
096:
097: /**
098: * Gets the number of times this thread was used.
099: * @return The number of times used.
100: */
101: public int getUsage() {
102: return count;
103: }
104:
105: /**
106: * Gets the time when this thread was created.
107: * @return Time in milliseconds when this was created.
108: */
109: public long getTime() {
110: return created.getTime();
111: }
112:
113: /**
114: * Gets the name of this JobInvoker.
115: * @return Name of the invoker.
116: */
117: public String getName() {
118: return this .name;
119: }
120:
121: /**
122: * Gets the status code for this thread (0 = sleeping, 1 = running job)
123: * @return 0 for sleeping or 1 when running a job.
124: */
125: public int getCurrentStatus() {
126: return this .statusCode;
127: }
128:
129: /**
130: * Gets the total time the current job has been running or 0 when sleeping.
131: * @return Total time the curent job has been running.
132: */
133: public long getCurrentRuntime() {
134: if (this .jobStart > 0) {
135: long now = System.currentTimeMillis();
136: return now - this .jobStart;
137: } else {
138: return 0;
139: }
140: }
141:
142: /**
143: * Get the current running job's name.
144: * @return String name of the current running job.
145: */
146: public String getJobName() {
147: if (this .statusCode == 1) {
148: if (this .currentJob != null) {
149: return this .currentJob.getJobName();
150: } else {
151: return "WARNING: Invalid Job!";
152: }
153: } else {
154: return null;
155: }
156: }
157:
158: /**
159: * Returns the name of the service being run.
160: * @return The name of the service being run.
161: */
162: public String getServiceName() {
163: String serviceName = null;
164: if (this .statusCode == 1) {
165: if (this .currentJob != null) {
166: if (this .currentJob instanceof GenericServiceJob) {
167: GenericServiceJob gsj = (GenericServiceJob) this .currentJob;
168: serviceName = gsj.getServiceName();
169: }
170: }
171: }
172: return serviceName;
173: }
174:
175: /**
176: * Kill this invoker thread.s
177: */
178: public void kill() {
179: this .stop();
180: this .statusCode = -1;
181: this .thread.interrupt();
182: this .thread = null;
183: }
184:
185: public synchronized void run() {
186: while (run) {
187: Job job = jp.next();
188:
189: if (job == null) {
190: try {
191: wait(wait);
192: } catch (InterruptedException ie) {
193: Debug.logError(ie,
194: "JobInvoker.run() : InterruptedException",
195: module);
196: stop();
197: }
198: } else {
199: // setup the current job settings
200: this .currentJob = job;
201: this .statusCode = 1;
202: this .jobStart = System.currentTimeMillis();
203:
204: // execute the job
205: if (Debug.verboseOn())
206: Debug.logVerbose("Invoker: " + thread.getName()
207: + " executing job -- " + job.getJobName(),
208: module);
209: job.exec();
210: if (Debug.verboseOn())
211: Debug.logVerbose("Invoker: " + thread.getName()
212: + " finished executing job -- "
213: + job.getJobName(), module);
214:
215: // clear the current job settings
216: this .currentJob = null;
217: this .statusCode = 0;
218: this .jobStart = 0;
219:
220: count++;
221: if (Debug.verboseOn())
222: Debug.logVerbose("Invoker: " + thread.getName()
223: + " (" + count + ") total.", module);
224: }
225: long diff = (new Date().getTime() - this .getTime());
226:
227: if (getTTL() > 0 && diff > getTTL())
228: jp.removeThread(this );
229: }
230: if (Debug.verboseOn())
231: Debug
232: .logVerbose(
233: "Invoker: " + thread.getName()
234: + " dead -- "
235: + UtilDateTime.nowTimestamp(),
236: module);
237: }
238:
239: private long getTTL() {
240: long ttl = THREAD_TTL;
241:
242: try {
243: ttl = Long.parseLong(ServiceConfigUtil.getElementAttr(
244: "thread-pool", "ttl"));
245: } catch (NumberFormatException nfe) {
246: Debug.logError(
247: "Problems reading values from serviceengine.xml file ["
248: + nfe.toString() + "]. Using defaults.",
249: module);
250: }
251: return ttl;
252: }
253: }
|