cleanup in Application:

* make init(), start() and stop() synchronized
* suppress some logging messages if using default values
  (cache size, preallocated evaluators)
* do not null out freeThreads stack in stop() so we don't have to worry
  about calling releaseEvaluator() in stopped applications
* replace boolean stopped field with boolean running and add
  public synchronized isRunning() accessor
* if preallocating multiple evaluators only init scripting engine
  on the first one
* move invocation of onStart() from start() to scheduler thread
This commit is contained in:
hns 2004-02-19 14:12:39 +00:00
parent 7bfb70430e
commit df1c131648
2 changed files with 38 additions and 37 deletions

View file

@ -82,7 +82,7 @@ public final class Application implements IPathElement, Runnable {
*/ */
protected Stack freeThreads; protected Stack freeThreads;
protected Vector allThreads; protected Vector allThreads;
boolean stopped = false; boolean running = false;
boolean debug; boolean debug;
long starttime; long starttime;
Hashtable sessions; Hashtable sessions;
@ -273,7 +273,7 @@ public final class Application implements IPathElement, Runnable {
/** /**
* Get the application ready to run, initializing the evaluators and type manager. * Get the application ready to run, initializing the evaluators and type manager.
*/ */
public void init() public synchronized void init()
throws DatabaseException, ScriptingException, MalformedURLException { throws DatabaseException, ScriptingException, MalformedURLException {
// create and init type mananger // create and init type mananger
@ -318,12 +318,16 @@ public final class Application implements IPathElement, Runnable {
// not parsable as number, keep 0 // not parsable as number, keep 0
} }
logEvent("Starting "+minThreads+" evaluator(s) for " + name); if (minThreads > 0) {
logEvent("Starting "+minThreads+" evaluator(s) for " + name);
}
for (int i = 0; i < minThreads; i++) { for (int i = 0; i < minThreads; i++) {
RequestEvaluator ev = new RequestEvaluator(this); RequestEvaluator ev = new RequestEvaluator(this);
ev.initScriptingEngine(); if (i == 0) {
ev.initScriptingEngine();
}
freeThreads.push(ev); freeThreads.push(ev);
allThreads.addElement(ev); allThreads.addElement(ev);
} }
@ -363,24 +367,10 @@ public final class Application implements IPathElement, Runnable {
/** /**
* Create and start scheduler and cleanup thread * Create and start scheduler and cleanup thread
*/ */
public void start() { public synchronized void start() {
starttime = System.currentTimeMillis(); starttime = System.currentTimeMillis();
// read in standard prototypes to make first request go faster running = true;
// typemgr.updatePrototype("root");
// typemgr.updatePrototype("global");
// as first thing, invoke global onStart() function
RequestEvaluator eval = getEvaluator();
try {
eval.invokeInternal(null, "onStart", new Object[0]);
} catch (Exception ignore) {
logEvent("Error in " + name + "/onStart(): " + ignore);
} finally {
if (!stopped) {
releaseEvaluator(eval);
}
}
worker = new Thread(this, "Worker-" + name); worker = new Thread(this, "Worker-" + name);
worker.setPriority(Thread.NORM_PRIORITY + 1); worker.setPriority(Thread.NORM_PRIORITY + 1);
@ -390,8 +380,8 @@ public final class Application implements IPathElement, Runnable {
/** /**
* This is called to shut down a running application. * This is called to shut down a running application.
*/ */
public void stop() { public synchronized void stop() {
stopped = true; running = false;
// stop all threads, this app is going down // stop all threads, this app is going down
if (worker != null) { if (worker != null) {
@ -411,7 +401,7 @@ public final class Application implements IPathElement, Runnable {
// remove evaluators // remove evaluators
allThreads.removeAllElements(); allThreads.removeAllElements();
freeThreads = null; freeThreads.clear();
// shut down node manager and embedded db // shut down node manager and embedded db
try { try {
@ -441,11 +431,15 @@ public final class Application implements IPathElement, Runnable {
} }
public synchronized boolean isRunning() {
return running;
}
/** /**
* Returns a free evaluator to handle a request. * Returns a free evaluator to handle a request.
*/ */
protected RequestEvaluator getEvaluator() { private RequestEvaluator getEvaluator() {
if (stopped) { if (!running) {
throw new ApplicationStoppedException(); throw new ApplicationStoppedException();
} }
@ -464,8 +458,8 @@ public final class Application implements IPathElement, Runnable {
synchronized (this) { synchronized (this) {
// allocate a new evaluator // allocate a new evaluator
if (allThreads.size() < maxThreads) { if (allThreads.size() < maxThreads) {
logEvent("Starting evaluator " + (allThreads.size() + 1) + logEvent("Starting engine " + (allThreads.size() + 1) +
" for application " + name); " for " + name);
RequestEvaluator ev = new RequestEvaluator(this); RequestEvaluator ev = new RequestEvaluator(this);
@ -1383,6 +1377,17 @@ public final class Application implements IPathElement, Runnable {
* kicking out expired user sessions. * kicking out expired user sessions.
*/ */
public void run() { public void run() {
// as first thing, invoke global onStart() function
RequestEvaluator eval = getEvaluator();
try {
eval.invokeInternal(null, "onStart", new Object[0]);
} catch (Exception xcept) {
logEvent("Error in " + name + "/onStart(): " + xcept);
} finally {
releaseEvaluator(eval);
}
// interval between session cleanups // interval between session cleanups
long sessionCleanupInterval = 60000; long sessionCleanupInterval = 60000;
long lastSessionCleanup = System.currentTimeMillis(); long lastSessionCleanup = System.currentTimeMillis();
@ -1441,7 +1446,7 @@ public final class Application implements IPathElement, Runnable {
logEvent("Error cleaning up sessions: " + cx); logEvent("Error cleaning up sessions: " + cx);
cx.printStackTrace(); cx.printStackTrace();
} finally { } finally {
if (!stopped && thisEvaluator != null) { if (thisEvaluator != null) {
releaseEvaluator(thisEvaluator); releaseEvaluator(thisEvaluator);
} }
} }
@ -1475,7 +1480,7 @@ public final class Application implements IPathElement, Runnable {
try { try {
thisEvaluator = getEvaluator(); thisEvaluator = getEvaluator();
} catch (RuntimeException rt) { } catch (RuntimeException rt) {
if (!stopped) { if (running) {
logEvent("couldn't execute " + j + logEvent("couldn't execute " + j +
", maximum thread count reached"); ", maximum thread count reached");
@ -1500,9 +1505,7 @@ public final class Application implements IPathElement, Runnable {
} catch (Exception ex) { } catch (Exception ex) {
logEvent("error running " + j + ": " + ex.toString()); logEvent("error running " + j + ": " + ex.toString());
} finally { } finally {
if (!stopped) { releaseEvaluator(thisEvaluator);
releaseEvaluator(thisEvaluator);
}
} }
} }
} }
@ -1956,9 +1959,7 @@ public final class Application implements IPathElement, Runnable {
} catch (Exception ex) { } catch (Exception ex) {
// gets logged in RequestEvaluator // gets logged in RequestEvaluator
} finally { } finally {
if (!stopped) { releaseEvaluator(thisEvaluator);
releaseEvaluator(thisEvaluator);
}
thisEvaluator = null; thisEvaluator = null;
activeCronJobs.remove(job.getName()); activeCronJobs.remove(job.getName());
} }

View file

@ -270,7 +270,7 @@ public final class RequestEvaluator implements Runnable {
// specified in the property file. // specified in the property file.
res.status = 404; res.status = 404;
String notFoundAction = app.props.getProperty("notFound", String notFoundAction = app.props.getProperty("notfound",
"notfound"); "notfound");
currentElement = root; currentElement = root;
@ -896,7 +896,7 @@ public final class RequestEvaluator implements Runnable {
} }
private synchronized void checkThread() { private synchronized void checkThread() {
if (app.stopped) { if (!app.isRunning()) {
throw new ApplicationStoppedException(); throw new ApplicationStoppedException();
} }