parent $utilities
object $scheduler
var $root child_index 0
var $root owners [$scheduler]
var $root fertile 0
var $root inited 1
var $scheduler task_index 1
var $scheduler task_queue []
var $user password 0
var $user connected_at 0
var $user last_command_at 0
var $user connections []
var $user creation_time 758802496
var $user action ""
var $root owned [$scheduler]
var $root info []
var $root manager $scheduler
var $root writable [$scheduler]
var $root readable ['parameters, 'methods, 'code]
var $root dbref 'scheduler
var $scheduler sub_schedulers [$heart]
method remove_first_task
var len, i, min;
// sender must be an agent, or admin
catch any {
if (caller() != this())
throw(~perm, "Invalid call to private method");
len = listlen(task_queue);
i = 1;
while (i != len) {
min = len;
if (((i * 2) < len) && (((task_queue[i * 2])[2]) < ((task_queue[min])[2])))
min = i * 2;
if ((((i * 2) + 1) < len) && (((task_queue[(i * 2) + 1])[2]) < ((task_queue[min])[2])))
min = (i * 2) + 1;
task_queue = replace(task_queue, i, task_queue[min]);
i = min;
}
task_queue = sublist(task_queue, 1, len - 1);
} with handler {
// $sys.log(traceback());
}
if (!task_queue)
task_index = 1;
.
method task_queue
// sender must be system, for now
.perms(sender(), 'system);
return task_queue;
.
method del_task
arg tid;
var task;
// sender must be system, for now.
.perms(sender(), 'system);
if (type(tid) != 'integer)
throw(~type, "Task Identification must be an integer");
for task in (task_queue) {
if ((task[1]) == tid) {
task_queue = delete(task_queue, task in task_queue);
return 1;
}
}
throw(~tasknf, "No task found by that TID");
.
method add_task
arg time, method, [args];
var task, i, tid, flags;
// use `@info $scheduler' for more information.
// [tid, time, time(), sender(), caller(), method, flags, args]
// 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?");
//
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];
task = [tid, time, time(), sender(), caller(), method, flags, args];
task_queue = task_queue + [task];
i = listlen(task_queue);
//
while ((i > 1) && ((task[2]) < (((task_queue[i / 2])[2]) + ((task_queue[i / 2])[3])))) {
task_queue = replace(task_queue, i, task_queue[i / 2]);
i = i / 2;
}
task_queue = replace(task_queue, i, task);
.
method pulse
var task, sub;
// called by $sys.heartbeat
if (caller() != $sys)
throw(~perm, "Sender is not system");
while (task_queue && (time() > (((task_queue[1])[2]) + ((task_queue[1])[3])))) {
task = task_queue[1];
(| ._run_task(task) |);
.remove_first_task();
}
// call sub schedulers
for sub in (sub_schedulers)
(| sub.pulse() |);
.
method _run_task
arg task;
var code, args, a;
// called by $scheduler only
if (caller() != this())
throw(~perm, "Caller is not this");
catch any {
// setup the args by hand, becuase we use eval and it expects a string
args = task[8];
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[6])) + "(") + args) + ");";
// run it through eval as the sender():
(task[5]).eval([code], task[4]);
} with handler {
// bounce the errors to the person, or to the system board if it's 'system
//catch any {
(| (task[4]).tell(["SCHEDULER ERROR: ", @traceback()]) |);
// } with handler {
// if ('system in task[7]) {
// $channels.announce('System, traceback()[1]);
// $channels.announce('System, "task: " + $data.unparse(task));
// }
// }
}
.
method sys_add_task
arg time, method, sender, caller, flags, [args];
var task, i, tid;
// use `@info $scheduler' for more information.
// [tid, time, time(), sender(), caller(), method, flags, args]
//
if (!($sys.is_agent(sender())))
throw(~perm, "Sender is not an agent or admin, use .add_task()");
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?");
if (!valid(sender))
throw(~type, "The argument for sender is not a valid object");
if (!valid(caller))
throw(~type, "The argument for caller is not a valid object");
if (type(flags) != 'list)
throw(~type, "Send flags as a list of symbols");
//
task_index = task_index + 1;
tid = task_index;
// flags can be set in a system only add_task, for now set them as 'system
task = [tid, time, time(), sender, caller, method, flags, args];
task_queue = task_queue + [task];
//
i = listlen(task_queue);
while ((i > 1) && ((task[2]) < (((task_queue[i / 2])[2]) + ((task_queue[i / 2])[3])))) {
task_queue = replace(task_queue, i, task_queue[i / 2]);
i = i / 2;
}
task_queue = replace(task_queue, i, task);
.
method add_sub_scheduler
arg object;
if (!($sys.is_admin(sender())))
throw(~perm, "Only admins may add sub schedulers.");
if (type(object) != 'dbref)
throw(~type, "Object must be a dbref.");
sub_schedulers = [@sub_schedulers, object];
.
method del_sub_scheduler
arg object;
var pos, s;
if (!($sys.is_admin(sender())))
throw(~perm, "Only admins may delete sub schedulers.");
if (type(object) != 'dbref)
throw(~type, "Object must be a dbref.");
pos = object in sub_schedulers;
if (!pos)
throw(~objnf, "Object not a sub schedulers.");
s = [];
if (pos > 1)
s = [@s, sublist(sub_schedulers, 1, pos - 1)];
if (s < listlen(sub_schedulers))
s = [@s, sublist(sub_schedulers, pos + 1)];
sub_schedulers = s;
.