Monday, November 08, 2010 at 12:05 AM.
system.verbs.builtins.scheduler.monitor
<<Changes
<<10/17/08; 9:28:10 AM by DW
<<Wired off the confirmation dialog on startup.
<<The confirmation dialog on startup is meaningless for a variety of reasons:
<<1. It only seems to apply to the nightlyTasks process, which in the OPML Editor does nothing.
<<2. What the fuck does it mean anyway? I've never had the patience to find out.
<<3. There already is code there for servers that go ahead and do whatever it does without the confirming dialog.
<<Sun, 07 Mar 1999 11:25:31 GMT by AR
<<Convert pre-6.0 tasks which are string objects to script objects.
<<12/18/98; 12:05:59 PM by DW
<<Major rewrite, added logging, scripts can be addresses
<<12/14/98; 11:11:46 PM by DW
<<Logging goes thru log.add
<<Mon, Aug 3, 1998 at 5:12:36 PM by PBS
<<Restore oldTarget from within a try (in case it's disappeared).
<<Fri, Jul 24, 1998 at 1:06:04 PM by PBS
<<Removed call to scheduler.init.
<<It's called from system.startup.startupScript.
<<Don't call target.clear -- instead restore the old target.
<<9/9/99; 6:35:08 PM by DW
<<added support for user.scheduler.threads
<<6/29/99; 5:59:08 PM by DW
<<added support for user.scheduler.threads
<<Called from the agent, once a minute.
<<We check the task list to see if any are ready to run.
<<If so, we run it and then check the next task.
<<About scheduler.currentTask:
<<Before your script runs this global is set.
<<You can use this table to store information between runs,
<<scheduler.currentTask^.xxx = 12
local (adrtasks = @user.scheduler.tasks, cttasks = sizeOf (adrtasks^), now = clock.now ());
on reschedule (adrtask) { //reschedule the task for another run
local (minutesbetweenruns = adrtask^.minutesbetweenruns);
if minutesbetweenruns > 0 { <<don't try to reschedule one-time tasks
while now >= adrtask^.tasktime {
local (day, month, year, hour, minute, second);
date.get (adrtask^.tasktime, @day, @month, @year, @hour, @minute, @second);
adrtask^.tasktime = date.set (day, month, year, hour, minute + minutesBetweenRuns, 0)}}
else {
if minutesbetweenruns == 0 {
adrtask^.completed = true}}};
if user.scheduler.prefs.startingup { //confirm that user wants to run awaiting longterm tasks
user.scheduler.prefs.startingup = false;
local (i);
for i = 1 to cttasks {
local (adrtask = @adrtasks^ [i]);
with adrtask^ {
if now >= taskTime { <<it's ready to run
local (flreschedule = true);
if minutesBetweenRuns > 60 {
if user.scheduler.prefs.reschedule {
if false { //user.scheduler.prefs.confirmStartupTasks -- 10/17/08 by DW -- wired off
if dialog.confirm ("Scheduler startup: \"" + nameOf (adrtask^) + "\" is ready to run.") {
flreschedule = false}}
else {
flreschedule = false}}}; //PBS 2/18/99: automatically run the pending tasks if confirmStartupTasks is false (this change is for Frontier servers)
if flreschedule {
reschedule (adrtask)}}}}};
local (logtable); new (tabletype, @logtable); //globals for all the tasks to share, used in logging
local (i, ctran = 0, cterrors = 0, adrtask);
for i = 1 to cttasks { //run tasks that are ready
adrtask = @adrtasks^ [i];
if now >= adrtask^.taskTime { //it's ready to run
adrtask^.ctruns++;
scheduler.currentTask = adrtask; //global, available to task
try {
on callWithLogging (adrscript) {
new (tabletype, @logtable.taskInfo);
try {
callScript (string (adrscript), {}, @logtable)}
else {
logtable.taskinfo.scriptError = tryError};
table.rename (@logtable.taskInfo, string (adrscript))};
case typeof (adrtask^.script) {
scripttype {
callWithLogging (@adrtask^.script)};
addresstype {
local (nomad = adrtask^.script);
while typeof (nomad^) != scripttype {
nomad = nomad^};
callWithLogging (nomad)}}
else { //convert a pre-6.0 scheduled task from string type to script type and run it
local (adrscript = @adrtask^.script);
script.newScriptObject (string (adrscript^), adrscript);
script.compile (adrscript); //make sure it is valid UserTalk
callWithLogging (adrscript)};
adrtask^.error = "";
reschedule (adrtask)}
else {
adrtask^.error = tryError;
cterrors++};
ctran++}};
if defined (scheduler.currentTask) {
delete (@scheduler.currentTask)};
bundle { //delete one-time tasks that have been run
local (i);
for i = cttasks downto 1 { //delete one-time tasks that have been run
local (adrtask = @adrtasks^ [i]);
if defined (adrtask^.completed) { //a one-time task that's done
delete (adrtask)}}};
bundle { //do logging
if ctran > 0 {
if user.scheduler.prefs.keepLog {
local (item = { "Ran " + ctran + " tasks"});
if cterrors > 0 {
local (i);
item [1] = item [1] + ". " + cterrors + " errors.";
for i = cttasks downto 1 {
local (errorstring = adrtasks^ [i].error);
if errorstring != "" {
local (s = nameOf (adrtasks^ [i]) + ": " + errorstring);
item = item + {s}}}};
log.add (item, "schedulerMonitor")};
if user.scheduler.prefs.logInGuestDatabase {
log.addToGuestDatabase ("schedulerMonitor", flHourlyRoll:true)^ = logtable}}};
bundle { //start threads that need starting, keep threads running
scheduler.monitorThreads ()}
This listing is for code that runs in the OPML Editor environment. I created these listings because I wanted the search engines to index it, so that when I want to look up something in my codebase I don't have to use the much slower search functionality in my object database. Dave Winer.