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 Vector allThreads;
boolean stopped = false;
boolean running = false;
boolean debug;
long starttime;
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.
*/
public void init()
public synchronized void init()
throws DatabaseException, ScriptingException, MalformedURLException {
// create and init type mananger
@ -318,12 +318,16 @@ public final class Application implements IPathElement, Runnable {
// 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++) {
RequestEvaluator ev = new RequestEvaluator(this);
ev.initScriptingEngine();
if (i == 0) {
ev.initScriptingEngine();
}
freeThreads.push(ev);
allThreads.addElement(ev);
}
@ -363,24 +367,10 @@ public final class Application implements IPathElement, Runnable {
/**
* Create and start scheduler and cleanup thread
*/
public void start() {
public synchronized void start() {
starttime = System.currentTimeMillis();
// read in standard prototypes to make first request go faster
// 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);
}
}
running = true;
worker = new Thread(this, "Worker-" + name);
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.
*/
public void stop() {
stopped = true;
public synchronized void stop() {
running = false;
// stop all threads, this app is going down
if (worker != null) {
@ -411,7 +401,7 @@ public final class Application implements IPathElement, Runnable {
// remove evaluators
allThreads.removeAllElements();
freeThreads = null;
freeThreads.clear();
// shut down node manager and embedded db
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.
*/
protected RequestEvaluator getEvaluator() {
if (stopped) {
private RequestEvaluator getEvaluator() {
if (!running) {
throw new ApplicationStoppedException();
}
@ -464,8 +458,8 @@ public final class Application implements IPathElement, Runnable {
synchronized (this) {
// allocate a new evaluator
if (allThreads.size() < maxThreads) {
logEvent("Starting evaluator " + (allThreads.size() + 1) +
" for application " + name);
logEvent("Starting engine " + (allThreads.size() + 1) +
" for " + name);
RequestEvaluator ev = new RequestEvaluator(this);
@ -1383,6 +1377,17 @@ public final class Application implements IPathElement, Runnable {
* kicking out expired user sessions.
*/
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
long sessionCleanupInterval = 60000;
long lastSessionCleanup = System.currentTimeMillis();
@ -1441,7 +1446,7 @@ public final class Application implements IPathElement, Runnable {
logEvent("Error cleaning up sessions: " + cx);
cx.printStackTrace();
} finally {
if (!stopped && thisEvaluator != null) {
if (thisEvaluator != null) {
releaseEvaluator(thisEvaluator);
}
}
@ -1475,7 +1480,7 @@ public final class Application implements IPathElement, Runnable {
try {
thisEvaluator = getEvaluator();
} catch (RuntimeException rt) {
if (!stopped) {
if (running) {
logEvent("couldn't execute " + j +
", maximum thread count reached");
@ -1500,9 +1505,7 @@ public final class Application implements IPathElement, Runnable {
} catch (Exception ex) {
logEvent("error running " + j + ": " + ex.toString());
} finally {
if (!stopped) {
releaseEvaluator(thisEvaluator);
}
releaseEvaluator(thisEvaluator);
}
}
}
@ -1956,9 +1959,7 @@ public final class Application implements IPathElement, Runnable {
} catch (Exception ex) {
// gets logged in RequestEvaluator
} finally {
if (!stopped) {
releaseEvaluator(thisEvaluator);
}
releaseEvaluator(thisEvaluator);
thisEvaluator = null;
activeCronJobs.remove(job.getName());
}

View file

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