2 * The Submit Daemon: Tasks
4 * (c) 2007 Martin Mares <mj@ucw.cz>
9 #include "ucw/fastbuf.h"
10 #include "ucw/stkstring.h"
11 #include "ucw/simple-lists.h"
12 #include "ucw/mempool.h"
13 #include "sherlock/object.h"
24 static clist extensions;
25 static clist open_data_extensions;
28 tasks_conf_commit(void *p UNUSED)
30 // We do not do any journaling here as we do not switch config files on the fly
31 CLIST_FOR_EACH(struct task *, t, task_list)
33 clist_init(&t->parts);
36 for (uns i=1; i<=t->open_data; i++)
37 simp_append(cf_pool, &t->parts)->s = mp_printf(cf_pool, "%02d", i);
38 t->extensions = &open_data_extensions;
42 simp_append(cf_pool, &t->parts)->s = t->name;
43 t->extensions = &extensions;
49 static struct cf_section task_conf = {
52 CF_STRING("Name", PTR_TO(struct task, name)),
53 CF_UNS("OpenData", PTR_TO(struct task, open_data)),
54 CF_UNS("MaxSize", PTR_TO(struct task, max_size)),
59 struct cf_section tasks_conf = {
60 CF_COMMIT(tasks_conf_commit),
62 CF_LIST("Task", &task_list, &task_conf),
63 CF_LIST("Extension", &extensions, &cf_string_list_config),
64 CF_LIST("OpenDataExt", &open_data_extensions, &cf_string_list_config),
72 CLIST_FOR_EACH(struct task *, t, task_list)
73 if (!strcasecmp(t->name, name))
79 part_exists_p(struct task *t, char *name)
81 CLIST_FOR_EACH(simp_node *, p, t->parts)
82 if (!strcmp(p->s, name))
88 ext_exists_p(struct task *t, char *ext)
90 CLIST_FOR_EACH(simp_node *, x, *t->extensions)
91 if (!strcmp(x->s, ext))
97 user_exists_p(char *user)
99 char *fn = stk_printf("solutions/%s", user);
101 return !stat(fn, &st) && S_ISDIR(st.st_mode);
105 task_load_status(struct conn *c)
107 struct fastbuf *fb = bopen_try(stk_printf("solutions/%s/status", c->user), O_RDONLY, 4096);
108 c->task_status = obj_new(c->pool);
111 obj_read(fb, c->task_status);
117 task_lock_status(struct conn *c)
119 ASSERT(!c->task_lock_fd);
120 if ((c->task_lock_fd = open(stk_printf("solutions/%s/status.lock", c->user), O_RDWR | O_CREAT | O_TRUNC, 0666)) < 0)
121 die("Cannot create task lock: %m");
124 .l_whence = SEEK_SET,
128 if (fcntl(c->task_lock_fd, F_SETLKW, &fl) < 0)
129 die("Cannot lock status file: %m");
134 task_unlock_status(struct conn *c, uns write_back)
136 ASSERT(c->task_lock_fd);
140 struct fastbuf *fb = bopen_tmp(4096);
141 obj_write(fb, c->task_status, BUCKET_TYPE_PLAIN);
143 bconfig(fb, BCONFIG_IS_TEMP_FILE, 0);
144 char *name = stk_printf("solutions/%s/status", c->user);
145 if (rename(fb->name, name) < 0)
146 die("Unable to rename %s to %s: %m", fb->name, name);
152 .l_whence = SEEK_SET,
156 if (fcntl(c->task_lock_fd, F_SETLKW, &fl) < 0)
157 die("Cannot unlock status file: %m");
162 task_status_find_task(struct conn *c, struct task *t, uns create)
164 for (struct oattr *a = obj_find_attr(c->task_status, 'T' + OBJ_ATTR_SON); a; a=a->same)
166 struct odes *o = a->son;
167 char *name = obj_find_aval(o, 'T');
169 if (!strcmp(name, t->name))
174 struct odes *o = obj_add_son(c->task_status, 'T' + OBJ_ATTR_SON);
175 obj_set_attr(o, 'T', t->name);
180 task_status_find_part(struct odes *to, char *part, uns create)
182 for (struct oattr *a = obj_find_attr(to, 'P' + OBJ_ATTR_SON); a; a=a->same)
184 struct odes *o = a->son;
185 char *name = obj_find_aval(o, 'P');
187 if (!strcmp(name, part))
192 struct odes *o = obj_add_son(to, 'P' + OBJ_ATTR_SON);
193 obj_set_attr(o, 'P', part);
198 task_record_history(char *user, char *task, char *part, char *ext, uns version, char *submitted_name)
203 time_t now = time(NULL);
204 struct tm *tm = localtime(&now);
206 if (strftime(prefix, sizeof(prefix), history_format, tm) <= 0)
208 msg(L_ERROR, "Error formatting history prefix: too long");
212 char *name = stk_printf("%s%s:%s:%s:v%d.%s", prefix, user, task, (strcmp(task, part) ? part : (char*)""), version, ext);
213 struct fastbuf *orig = bopen(submitted_name, O_RDONLY, 4096);
214 struct fastbuf *hist = bopen(name, O_WRONLY | O_CREAT | O_EXCL, 4096);
215 bbcopy_slow(orig, hist, ~0U);
221 task_submit_part(char *user, char *task, char *part, char *ext, uns version, struct fastbuf *fb)
223 char *dir = stk_printf("solutions/%s/%s", user, task);
224 char *name = stk_printf("%s/%s.%s", dir, part, ext);
227 if (stat(dir, &st) < 0 && errno == ENOENT && mkdir(dir, 0777) < 0)
228 die("Cannot create %s: %m", dir);
230 bconfig(fb, BCONFIG_IS_TEMP_FILE, 0);
231 if (rename(fb->name, name) < 0)
232 die("Cannot rename %s to %s: %m", fb->name, name);
234 task_record_history(user, task, part, ext, version, name);
238 task_delete_part(char *user, char *task, char *part, char *ext, uns version UNUSED)
240 char *dir = stk_printf("solutions/%s/%s", user, task);
241 char *name = stk_printf("%s/%s.%s", dir, part, ext);
242 if (unlink(name) < 0)
243 msg(L_ERROR, "Cannot delete %s: %m", name);