parent $utilities
object $scheduler_crag
var $root child_index 0
var $root owners [$scheduler_crag]
var $root owned [$scheduler_crag]
var $root fertile 0
var $root inited 1
var $scheduler_crag tasks <$small_first_heap_class, #[['key, 'run_time], ['data, [#[['tid, 7], ['run_time, 762498497], ['instime, 762498467], ['sender, $], ['caller, $], ['method, 'tell], ['flags, ['system]], ['owner, $], ['args, ["foo"]]], #[['tid, 8], ['run_time, 762498498], ['instime, 762498468], ['sender, $], ['caller, $], ['method, 'tell], ['flags, ['system]], ['owner, $], ['args, ["foo"]]], #[['tid, 9], ['run_time, 762498499], ['instime, 762498469], ['sender, $], ['caller, $], ['method, 'tell], ['flags, ['system]], ['owner, $], ['args, ["foo"]]], #[['tid, 10], ['run_time, 762498500], ['instime, 762498470], ['sender, $], ['caller, $], ['method, 'tell], ['flags, ['system]], ['owner, $], ['args, ["foo"]]], #[['tid, 11], ['run_time, 762498506], ['instime, 762498503], ['sender, $], ['caller, $], ['method, 'tell], ['flags, ['system]], ['owner, $], ['args, ["foo"]]]]]]>
var $scheduler_crag task_index 12
var $root manager $scheduler_crag
var $root writable [$scheduler_crag]
var $root readable ['parameters, 'methods, 'code]
var $root dbref 'scheduler_crag
method _insert_task
arg tid, extime, instime, sender, caller, method, flags, owner, args;
// inserts a task into the correct order. Callable only by this.
if (sender() != this())
throw(~perm, "Sender is not this");
tasks = tasks.add(#[['tid, tid], ['run_time, extime + instime], ['instime, instime], ['sender, sender], ['caller, caller], ['method, method], ['flags, flags], ['owner, owner], ['args, args]]);
.
method pulse
// called by $sys.heartbeat.
if (caller() != $sys)
throw(~perm, "Sender is not system");
while ((tasks.length()) && ((time() > ((tasks.element(1))['run_time])) && (._run_task()))) {
// do nothing?
}
.
method _run_task
var task, code, args, a;
// called by $scheduler only
if (caller() != this())
throw(~perm, "Caller is not this");
task = tasks.element(1);
catch any {
// setup the args by hand, becuase we use eval and it expects a string
args = task['args];
if (args) {
for a in [1 .. listlen(args)]
args = replace(args, a, $data.unparse(args[a]));
args = $list.to_string(args, ",");
} else {
args = "";
}
code = ((("." + tostr(task['method])) + "(") + args) + ");";
// run it through eval as the sender():
(task['caller]).eval([code], task['sender]);
return ._del_task(1);
} with handler {
// bounce the errors to the person, or to the system board if it's 'system
catch any {
(task['owner]).tell(["SCHEDULER ERROR: ", @traceback()]);
} with handler {
if ((task['owner]) == 'system) {
$channels.announce('System, traceback()[1]);
$channels.announce('System, "task: " + ($data.unparse(task)));
}
}
return 0;
}
.
method queue
arg [owner];
var task, atasks, queue, t;
// return tasks queued under owner, or return all if is admin.
if ((!owner) && ($sys.is_admin(sender())))
owner = 'all;
else
owner = [@owner, sender()][1];
// if (owner == 'all)
// atasks = tasks;
// else
// atasks = owners[owner];
if (owner || (!($sys.is_admin(sender())))) {
queue = $small_first_heap_class.new([], 'run_time);
for t in [1 .. queue.length()] {
if (((tasks.element(t))['owner]) == owner)
queue.add(tasks.element(t));
}
} else {
queue = tasks;
}
return queue;
.
method del_task
arg tid;
var task;
if (type(tid) != 'integer)
throw(~type, "Task Identification must be an integer");
if (!(tid in tasks))
throw(~tasknf, ("No task found by the TID of `" + tostr(tid)) + "'");
if ((task_owner[tid]) != sender())
throw(~perm, "Sender does not have permissions to kill this task.");
// ok, delete it
._del_task(tid in ($list.slice(.tasks(), 'tid)));
.
method tasks
return tasks.data();
.
method sys_del_task
arg tid;
var task;
// sender must be system
if (!($sys.is_agent(sender())))
throw(~perm, "Sender does not have system privelages");
if (type(tid) != 'integer)
throw(~type, "Task Identification must be an integer");
if (!(tid in tasks))
throw(~tasknf, ("No task found by the TID of `" + tostr(tid)) + "'");
// ok, delete it.
._del_task(tid in ($list.slice(.tasks(), 'tid)));
.
method _del_task
arg task;
// assumes that the $scheduler has already checked everything.
if (sender() != this())
throw(~perm, "Sender is not this");
tasks = tasks.del(task);
.
method sys_bump_task
arg tid;
var task_index, task;
// bumps a task up to be executed next
if ((!($sys.is_agent(sender()))) || (!($sys.is_admin(sender()))))
throw(~perm, "Sender does not have system perms");
// the meat
task_index = tid in (.tasks());
if (!task_index)
throw(~tasknf, "Task not found.");
if (task_index == 1)
return;
task = tasks.element(task_index);
tasks = tasks.del(task_index);
task = task.replace('run_time, $list.min(((tasks.element(1))['run_time]) - 1, time()));
tasks = tasks.add(task);
.
method add_task
arg time, method, [args];
var tid, flags, owner, task;
// use `@info $scheduler' for more information.
// time is seconds from insertion time that it will be run (ie 300 == 5 mins)
//
if ((type(time) != 'integer) || ((type(method) != 'symbol) || (type(args) != 'list)))
throw(~type, "Arguments are not an integer, symbol, and list.");
if (time < 1)
throw(~time, "Time is negative.");
if (time > 31536000)
throw(~time, "Try to schedule a task LESS than a year from now?");
// get TID and increment the TID index
task_index = task_index + 1;
tid = task_index;
// flags can be set in a system only add_task, for now set them as 'system
flags = ['system];
// check the owner of the object sending the task
owner = sender().owner();
// do it.
task = [tid, time, time(), sender(), caller(), method, flags, owner, args];
._insert_task(@task);
.