* Extract session cleanup and cron job invoker code from run()
into separate cleanupSessions() and executeCronJobs() methods * Add some missing JavaDoc tags
This commit is contained in:
parent
42a088ef58
commit
b316462c69
1 changed files with 159 additions and 133 deletions
|
@ -478,7 +478,7 @@ public final class Application implements IPathElement, Runnable {
|
||||||
/**
|
/**
|
||||||
* Returns true if this app is currently running
|
* Returns true if this app is currently running
|
||||||
*
|
*
|
||||||
* @return
|
* @return true if the app is running
|
||||||
*/
|
*/
|
||||||
public synchronized boolean isRunning() {
|
public synchronized boolean isRunning() {
|
||||||
return running;
|
return running;
|
||||||
|
@ -487,7 +487,7 @@ public final class Application implements IPathElement, Runnable {
|
||||||
/**
|
/**
|
||||||
* Get the application directory.
|
* Get the application directory.
|
||||||
*
|
*
|
||||||
* @return
|
* @return the application directory, or first file based repository
|
||||||
*/
|
*/
|
||||||
public File getAppDir() {
|
public File getAppDir() {
|
||||||
return appDir;
|
return appDir;
|
||||||
|
@ -497,7 +497,7 @@ public final class Application implements IPathElement, Runnable {
|
||||||
* Get a comparator for comparing Resources according to the order of
|
* Get a comparator for comparing Resources according to the order of
|
||||||
* repositories they're contained in.
|
* repositories they're contained in.
|
||||||
*
|
*
|
||||||
* @return
|
* @return a comparator that sorts resources according to their repositories
|
||||||
*/
|
*/
|
||||||
public ResourceComparator getResourceComparator() {
|
public ResourceComparator getResourceComparator() {
|
||||||
return resourceComparator;
|
return resourceComparator;
|
||||||
|
@ -1406,8 +1406,9 @@ public final class Application implements IPathElement, Runnable {
|
||||||
public void run() {
|
public void run() {
|
||||||
|
|
||||||
// as first thing, invoke global onStart() function
|
// as first thing, invoke global onStart() function
|
||||||
RequestEvaluator eval = getEvaluator();
|
RequestEvaluator eval = null;
|
||||||
try {
|
try {
|
||||||
|
eval = getEvaluator();
|
||||||
eval.invokeInternal(null, "onStart", new Object[0]);
|
eval.invokeInternal(null, "onStart", new Object[0]);
|
||||||
} catch (Exception xcept) {
|
} catch (Exception xcept) {
|
||||||
logEvent("Error in " + name + "/onStart(): " + xcept);
|
logEvent("Error in " + name + "/onStart(): " + xcept);
|
||||||
|
@ -1416,149 +1417,33 @@ public final class Application implements IPathElement, Runnable {
|
||||||
}
|
}
|
||||||
|
|
||||||
// interval between session cleanups
|
// interval between session cleanups
|
||||||
long sessionCleanupInterval = 60000;
|
|
||||||
long lastSessionCleanup = System.currentTimeMillis();
|
long lastSessionCleanup = System.currentTimeMillis();
|
||||||
|
|
||||||
// logEvent ("Starting scheduler for "+name);
|
// logEvent ("Starting scheduler for "+name);
|
||||||
|
|
||||||
// loop-local cron job data
|
|
||||||
List cronJobs = null;
|
|
||||||
long lastCronParse = 0;
|
|
||||||
|
|
||||||
while (Thread.currentThread() == worker) {
|
while (Thread.currentThread() == worker) {
|
||||||
|
|
||||||
long now = System.currentTimeMillis();
|
// purge sessions
|
||||||
|
|
||||||
// check if we should clean up user sessions
|
|
||||||
if ((now - lastSessionCleanup) > sessionCleanupInterval) {
|
|
||||||
|
|
||||||
lastSessionCleanup = now;
|
|
||||||
|
|
||||||
// get session timeout
|
|
||||||
int sessionTimeout = 30;
|
|
||||||
|
|
||||||
try {
|
|
||||||
sessionTimeout = Math.max(0,
|
|
||||||
Integer.parseInt(props.getProperty("sessionTimeout",
|
|
||||||
"30")));
|
|
||||||
} catch (Exception ignore) {}
|
|
||||||
|
|
||||||
RequestEvaluator thisEvaluator = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
thisEvaluator = getEvaluator();
|
|
||||||
|
|
||||||
Map sessions = sessionMgr.getSessions();
|
|
||||||
|
|
||||||
Iterator it = sessions.values().iterator();
|
|
||||||
while (it.hasNext()) {
|
|
||||||
Session session = (Session) it.next();
|
|
||||||
|
|
||||||
if ((now - session.lastTouched()) > (sessionTimeout * 60000)) {
|
|
||||||
NodeHandle userhandle = session.userHandle;
|
|
||||||
|
|
||||||
if (userhandle != null) {
|
|
||||||
try {
|
|
||||||
Object[] param = { session.getSessionId() };
|
|
||||||
|
|
||||||
thisEvaluator.invokeInternal(userhandle, "onLogout", param);
|
|
||||||
} catch (Exception ignore) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sessionMgr.discardSession(session);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception cx) {
|
|
||||||
logEvent("Error cleaning up sessions: " + cx);
|
|
||||||
cx.printStackTrace();
|
|
||||||
} finally {
|
|
||||||
if (thisEvaluator != null) {
|
|
||||||
releaseEvaluator(thisEvaluator);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if ((cronJobs == null) || (props.lastModified() > lastCronParse)) {
|
lastSessionCleanup = cleanupSessions(lastSessionCleanup);
|
||||||
updateProperties();
|
} catch (Exception x) {
|
||||||
cronJobs = CronJob.parse(props);
|
logError("Error in session cleanup", x);
|
||||||
lastCronParse = props.lastModified();
|
|
||||||
}
|
|
||||||
} catch (Exception ex) {
|
|
||||||
logEvent ("error parsing CronJobs: " + ex);
|
|
||||||
ex.printStackTrace();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// execute cron jobs
|
||||||
try {
|
try {
|
||||||
Date date = new Date();
|
executeCronJobs();
|
||||||
List jobs = new ArrayList(cronJobs);
|
} catch (Exception x) {
|
||||||
|
logError("Error in cron job execution", x);
|
||||||
jobs.addAll(customCronJobs.values());
|
|
||||||
CronJob.sort(jobs);
|
|
||||||
|
|
||||||
logEvent("Running cron jobs: " + jobs);
|
|
||||||
if (!activeCronJobs.isEmpty()) {
|
|
||||||
logEvent("Cron jobs still running from last minute: " + activeCronJobs);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Iterator i = jobs.iterator(); i.hasNext();) {
|
|
||||||
CronJob job = (CronJob) i.next();
|
|
||||||
|
|
||||||
if (job.appliesToDate(date)) {
|
|
||||||
// check if the job is already active ...
|
|
||||||
if (activeCronJobs.containsKey(job.getName())) {
|
|
||||||
logEvent(job + " is still active, skipped in this minute");
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
RequestEvaluator evaluator;
|
|
||||||
|
|
||||||
try {
|
|
||||||
evaluator = getEvaluator();
|
|
||||||
} catch (RuntimeException rt) {
|
|
||||||
if (running) {
|
|
||||||
logEvent("couldn't execute " + job +
|
|
||||||
", maximum thread count reached");
|
|
||||||
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the job has a long timeout or we're already late during this minute
|
|
||||||
// the job is run from an extra thread
|
|
||||||
if ((job.getTimeout() > 20000) ||
|
|
||||||
(CronJob.millisToNextFullMinute() < 30000)) {
|
|
||||||
CronRunner runner = new CronRunner(evaluator, job);
|
|
||||||
|
|
||||||
activeCronJobs.put(job.getName(), runner);
|
|
||||||
runner.start();
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
evaluator.invokeInternal(null, job.getFunction(),
|
|
||||||
new Object[0], job.getTimeout());
|
|
||||||
} catch (Exception ex) {
|
|
||||||
logEvent("error running " + job + ": " + ex);
|
|
||||||
} finally {
|
|
||||||
releaseEvaluator(evaluator);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception ex) {
|
|
||||||
logEvent("error handling CronJobs: " + ex);
|
|
||||||
ex.printStackTrace();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
long sleepInterval = CronJob.millisToNextFullMinute();
|
long sleepInterval = 60000;
|
||||||
try {
|
try {
|
||||||
String sleepProp = props.getProperty("schedulerInterval");
|
String sleepProp = props.getProperty("schedulerInterval");
|
||||||
if (sleepProp != null) {
|
if (sleepProp != null) {
|
||||||
sleepInterval = Math.max(1000, Integer.parseInt(sleepProp)*1000);
|
sleepInterval = Math.max(1000, Integer.parseInt(sleepProp) * 1000);
|
||||||
|
} else {
|
||||||
|
sleepInterval = CronJob.millisToNextFullMinute();
|
||||||
}
|
}
|
||||||
} catch (Exception ignore) {
|
} catch (Exception ignore) {
|
||||||
// we'll use the default interval
|
// we'll use the default interval
|
||||||
|
@ -1584,6 +1469,147 @@ public final class Application implements IPathElement, Runnable {
|
||||||
logEvent("Scheduler for " + name + " exiting");
|
logEvent("Scheduler for " + name + " exiting");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Purge sessions that have not been used for a certain amount of time.
|
||||||
|
* This is called by run().
|
||||||
|
*
|
||||||
|
* @param lastSessionCleanup the last time sessions were purged
|
||||||
|
* @return the updated lastSessionCleanup value
|
||||||
|
*/
|
||||||
|
private long cleanupSessions(long lastSessionCleanup) {
|
||||||
|
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
long sessionCleanupInterval = 60000;
|
||||||
|
|
||||||
|
// check if we should clean up user sessions
|
||||||
|
if ((now - lastSessionCleanup) > sessionCleanupInterval) {
|
||||||
|
|
||||||
|
// get session timeout
|
||||||
|
int sessionTimeout = 30;
|
||||||
|
|
||||||
|
try {
|
||||||
|
sessionTimeout = Math.max(0,
|
||||||
|
Integer.parseInt(props.getProperty("sessionTimeout",
|
||||||
|
"30")));
|
||||||
|
} catch (Exception ignore) {
|
||||||
|
}
|
||||||
|
|
||||||
|
RequestEvaluator thisEvaluator = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
thisEvaluator = getEvaluator();
|
||||||
|
|
||||||
|
Map sessions = sessionMgr.getSessions();
|
||||||
|
|
||||||
|
Iterator it = sessions.values().iterator();
|
||||||
|
while (it.hasNext()) {
|
||||||
|
Session session = (Session) it.next();
|
||||||
|
|
||||||
|
if ((now - session.lastTouched()) > (sessionTimeout * 60000)) {
|
||||||
|
NodeHandle userhandle = session.userHandle;
|
||||||
|
|
||||||
|
if (userhandle != null) {
|
||||||
|
try {
|
||||||
|
Object[] param = {session.getSessionId()};
|
||||||
|
|
||||||
|
thisEvaluator.invokeInternal(userhandle, "onLogout", param);
|
||||||
|
} catch (Exception ignore) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sessionMgr.discardSession(session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception cx) {
|
||||||
|
logEvent("Error cleaning up sessions: " + cx);
|
||||||
|
cx.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
if (thisEvaluator != null) {
|
||||||
|
releaseEvaluator(thisEvaluator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return now;
|
||||||
|
} else {
|
||||||
|
return lastSessionCleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes cron jobs for the application, which are either
|
||||||
|
* defined in app.properties or via app.addCronJob().
|
||||||
|
* This method is called by run().
|
||||||
|
*/
|
||||||
|
private void executeCronJobs() {
|
||||||
|
// loop-local cron job data
|
||||||
|
List cronJobs = null;
|
||||||
|
long lastCronParse = 0;
|
||||||
|
|
||||||
|
if ((cronJobs == null) || (props.lastModified() > lastCronParse)) {
|
||||||
|
updateProperties();
|
||||||
|
cronJobs = CronJob.parse(props);
|
||||||
|
lastCronParse = props.lastModified();
|
||||||
|
}
|
||||||
|
|
||||||
|
Date date = new Date();
|
||||||
|
List jobs = new ArrayList(cronJobs);
|
||||||
|
|
||||||
|
jobs.addAll(customCronJobs.values());
|
||||||
|
CronJob.sort(jobs);
|
||||||
|
|
||||||
|
logEvent("Running cron jobs: " + jobs);
|
||||||
|
if (!activeCronJobs.isEmpty()) {
|
||||||
|
logEvent("Cron jobs still running from last minute: " + activeCronJobs);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Iterator i = jobs.iterator(); i.hasNext();) {
|
||||||
|
CronJob job = (CronJob) i.next();
|
||||||
|
|
||||||
|
if (job.appliesToDate(date)) {
|
||||||
|
// check if the job is already active ...
|
||||||
|
if (activeCronJobs.containsKey(job.getName())) {
|
||||||
|
logEvent(job + " is still active, skipped in this minute");
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
RequestEvaluator evaluator;
|
||||||
|
|
||||||
|
try {
|
||||||
|
evaluator = getEvaluator();
|
||||||
|
} catch (RuntimeException rt) {
|
||||||
|
if (running) {
|
||||||
|
logEvent("couldn't execute " + job +
|
||||||
|
", maximum thread count reached");
|
||||||
|
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the job has a long timeout or we're already late during this minute
|
||||||
|
// the job is run from an extra thread
|
||||||
|
if ((job.getTimeout() > 20000) ||
|
||||||
|
(CronJob.millisToNextFullMinute() < 30000)) {
|
||||||
|
CronRunner runner = new CronRunner(evaluator, job);
|
||||||
|
|
||||||
|
activeCronJobs.put(job.getName(), runner);
|
||||||
|
runner.start();
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
evaluator.invokeInternal(null, job.getFunction(),
|
||||||
|
new Object[0], job.getTimeout());
|
||||||
|
} catch (Exception ex) {
|
||||||
|
logEvent("error running " + job + ": " + ex);
|
||||||
|
} finally {
|
||||||
|
releaseEvaluator(evaluator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether a prototype is for scripting a java class, i.e. if there's an entry
|
* Check whether a prototype is for scripting a java class, i.e. if there's an entry
|
||||||
* for it in the class.properties file.
|
* for it in the class.properties file.
|
||||||
|
|
Loading…
Add table
Reference in a new issue