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; .