1 /* Copyright (C) 2000-2004 Thomas Bopp, Thorsten Hampel, Ludger Merkens
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 * $Id: tasks.pike,v 1.2 2009/08/07 15:22:36 nicke Exp $
19 inherit "/kernel/module";
21 #include <exception.h>
22 #include <attributes.h>
27 class tasks : public module{
38 #define DEBUG_TASK(s, args...) write("TASKS: "+s+"\n", args)
40 #define DEBUG_TASK(s, args...)
43 mapping mTasks = ([ ]);
45 Thread.Queue taskQueue; // task Queue
49 void task_debug(string s)
52 string l = log->get_content();
53 log->set_content(l+ "On "+ctime(time())+": "+ s+"<br/>");
61 add_data_storage(STORE_TASKS,retrieve_tasks, restore_tasks);
62 taskQueue = Thread.Queue();
64 start_thread(worker); // start 1 worker threads
74 object task = taskQueue->read();
75 string tdescribe = task->describe();
76 float tt = gauge(f_run_task(task));
77 int slow = (int)_Server->get_config("log_slow_tasks");
78 if ( slow && (int)(tt*1000.0) > slow )
79 get_module("log")->log("slow_requests", LOG_LEVEL_INFO,
80 "%s Task %s took %d ms",
81 timelib.event_time(time()), tdescribe,
85 if ( arrayp(err) && sizeof(err) == 3 && (err[2] & E_ACCESS) ) {
86 get_module("log")->log("security", LOG_LEVEL_DEBUG, "%O\n%O",
90 FATAL("Task failed with error: %O\n%O", err[0], err[1]);
93 DEBUG_TASK("Task succeeded !");
99 mapping retrieve_tasks()
101 if ( CALLER != _Database )
102 THROW("Caller is not database !", E_ACCESS);
103 mapping save = ([ ]);
104 foreach ( indices(mTasks), mixed idx)
105 if ( objectp(idx) ) {
107 foreach(mTasks[idx], object t ) {
108 if ( objectp(t) && !functionp(t->func) && objectp(t->obj))
109 save[idx] += ({ mkmapping(indices(t), values(t)) });
112 //werror("****** retrieve_tasks() = %O\n", save);
113 return ([ "tasks": save, "id": tid, ]);
119 void restore_tasks(mapping data)
121 if ( CALLER != _Database )
122 THROW("Caller is not database !", E_ACCESS);
123 foreach(indices(data["tasks"]), object o ) {
124 foreach(data["tasks"][o], mapping m)
126 LOG("Task="+sprintf("%O\n",m));
127 object t = add_task(o, m->obj, m->func,
128 m->params, m->descriptions);
138 * Add a task for a user or a general task. The task will be execute when
139 * the user logs in or after a time of t.
141 * @param object|int user_t - a user task, ask the user upon login
142 * @param object obj - the object to call a function
143 * @param string func - the task function to call
145 * @return the resulting task object (see Task.pmod)
148 add_task(int|object user_t, object obj, string|function func, array args, mapping desc)
150 object task = Task();
154 task->descriptions = desc;
161 if ( objectp(user_t) ) {
162 if ( !arrayp(mTasks[user_t]) )
163 mTasks[user_t] = ({ });
164 mTasks[user_t] += ({ task });
165 // do not save these tasks
169 task->exec_time = user_t;
170 if ( task->exec_time > time() ) {
171 DEBUG_TASK("New Task running later !");
172 call(run_task, time() - task->exec_time, task);
176 DEBUG_TASK("New Task immediate execution !");
178 // execute immediately or after time user_t
181 DEBUG_TASK("added %O (id="+task->tid+")", func);
182 require_save(STORE_TASKS);
187 array get_tasks(object user)
189 array tasks = mTasks[user] || ({ });
190 return tasks - ({ 0 });
194 object get_task(int tid)
204 void tasks_done(object user)
206 DEBUG_TASK("All Tasks done for "+ user->get_identifier());
207 mTasks[user] = ({ });
208 require_save(STORE_TASKS);
212 void f_run_task(object t)
217 DEBUG_TASK("Tasks: looking for %O\n", t->func);
218 if ( !functionp(t->func) ) {
219 if ( !objectp(t->obj) ) {
220 FATAL("Invalid Task %O\n", t->describe());
221 m_delete(mTasks, t->tid);
222 require_save(STORE_TASKS);
225 f = t->obj->find_function(t->func);
230 if ( !functionp(f) ) {
231 FATAL("Cannot find task '"+t->func+"' to execute !");
234 DEBUG_TASK("Running task " + t->tid + "(%O in %O) as %O\n",
238 DEBUG_TASK("Current user is %O", this_user());
242 if ( arrayp(t->params) )
243 err = catch(f(@t->params));
248 FATAL( "Error while running task (%O in %O) as %O: %O\n%O",
249 t->func, t->obj, t->user, err[0], err[1] );
252 DEBUG_TASK("Task " + t->tid + " success !");
253 m_delete(mTasks, t->tid);
254 err = catch(t->task_done());
256 FATAL( "Error while ending task (%O in %O) as %O: %O",
257 t->func, t->obj, t->user, err );
259 require_save(STORE_TASKS);
264 int run_task(int|object tid)
273 FATAL("Unable to perform task " + tid + ": no object.");
277 t->user = geteuid() || this_user();
278 DEBUG_TASK("Run Task %O in %O (id=%d) as %O",
289 string get_identifier() { return "tasks"; }
291 void create_group_exit(object grp, object user)
293 object dest = grp->query_attribute(GROUP_WORKROOM);
294 object wr = user->query_attribute(USER_WORKROOM);
295 array exits = wr->get_inventory_by_class(CLASS_EXIT);
297 // check if exit already exists in workarea
298 foreach ( exits, object ex )
299 if ( ex->get_exit() == dest )
303 object factory = _Server->get_factory(CLASS_EXIT);
304 object exit = factory->execute(
305 ([ "name": grp->parent_and_group_name() + " workarea", "exit_to": dest, ]) );
309 void join_invited_group(object grp, object user)
311 grp->add_member(user);
312 create_group_exit(grp, user);
315 void remove_group_exit(object grp, object user)
317 object wr = user->query_attribute(USER_WORKROOM);
319 foreach(wr->get_inventory_by_class(CLASS_EXIT), object exit)
320 if ( exit->get_exit() == grp->query_attribute(GROUP_WORKROOM) )