X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=submit%2Ftasks.c;h=d4801670075d90c221c3ed2be0ae2c83989ee30f;hb=b6013d244489aca80a904755ec2531874361185c;hp=4a6930319799983dae873420da09c8ed5d879174;hpb=92811b1aa5a791bc776b58afb241a7d93e737604;p=moe.git diff --git a/submit/tasks.c b/submit/tasks.c index 4a69303..d480167 100644 --- a/submit/tasks.c +++ b/submit/tasks.c @@ -8,20 +8,41 @@ #include "lib/conf.h" #include "lib/fastbuf.h" #include "lib/stkstring.h" +#include "lib/simple-lists.h" +#include "lib/mempool.h" #include "sherlock/object.h" #include #include #include +#include +#include #include "submitd.h" clist task_list; +static clist extensions; +static clist open_data_extensions; -static byte * -tasks_conf_init(void) +static char * +tasks_conf_commit(void *p UNUSED) { - clist_init(&task_list); + // We do not do any journaling here as we do not switch config files on the fly + CLIST_FOR_EACH(struct task *, t, task_list) + { + clist_init(&t->parts); + if (t->open_data) + { + for (uns i=1; i<=t->open_data; i++) + simp_append(cf_pool, &t->parts)->s = mp_printf(cf_pool, "%02d", i); + t->extensions = &open_data_extensions; + } + else + { + simp_append(cf_pool, &t->parts)->s = t->name; + t->extensions = &extensions; + } + } return NULL; } @@ -29,20 +50,24 @@ static struct cf_section task_conf = { CF_TYPE(struct task), CF_ITEMS { CF_STRING("Name", PTR_TO(struct task, name)), + CF_UNS("OpenData", PTR_TO(struct task, open_data)), + CF_UNS("MaxSize", PTR_TO(struct task, max_size)), CF_END } }; struct cf_section tasks_conf = { - CF_INIT(tasks_conf_init), + CF_COMMIT(tasks_conf_commit), CF_ITEMS { CF_LIST("Task", &task_list, &task_conf), + CF_LIST("Extension", &extensions, &cf_string_list_config), + CF_LIST("OpenDataExt", &open_data_extensions, &cf_string_list_config), CF_END } }; struct task * -task_find(byte *name) +task_find(char *name) { CLIST_FOR_EACH(struct task *, t, task_list) if (!strcasecmp(t->name, name)) @@ -51,11 +76,41 @@ task_find(byte *name) } int -user_exists_p(byte *user) +part_exists_p(struct task *t, char *name) +{ + CLIST_FOR_EACH(simp_node *, p, t->parts) + if (!strcmp(p->s, name)) + return 1; + return 0; +} + +int +ext_exists_p(struct task *t, char *ext) { - byte *fn = stk_printf("solutions/%s/status", user); + CLIST_FOR_EACH(simp_node *, x, *t->extensions) + if (!strcmp(x->s, ext)) + return 1; + return 0; +} + +int +user_exists_p(char *user) +{ + char *fn = stk_printf("solutions/%s", user); struct stat st; - return !stat(fn, &st) && S_ISREG(st.st_mode); + return !stat(fn, &st) && S_ISDIR(st.st_mode); +} + +void +task_load_status(struct conn *c) +{ + struct fastbuf *fb = bopen_try(stk_printf("solutions/%s/status", c->user), O_RDONLY, 4096); + c->task_status = obj_new(c->pool); + if (fb) + { + obj_read(fb, c->task_status); + bclose(fb); + } } void @@ -72,21 +127,13 @@ task_lock_status(struct conn *c) }; if (fcntl(c->task_lock_fd, F_SETLKW, &fl) < 0) die("Cannot lock status file: %m"); - - struct fastbuf *fb = bopen_try(stk_printf("solutions/%s/status", c->user), O_RDONLY, 4096); - c->task_status = obj_new(c->pool); - if (fb) - { - obj_read(fb, c->task_status); - bclose(fb); - } + task_load_status(c); } void task_unlock_status(struct conn *c, uns write_back) { ASSERT(c->task_lock_fd); - ASSERT(c->task_status); if (write_back) { @@ -94,7 +141,7 @@ task_unlock_status(struct conn *c, uns write_back) obj_write(fb, c->task_status, BUCKET_TYPE_PLAIN); brewind(fb); bconfig(fb, BCONFIG_IS_TEMP_FILE, 0); - byte *name = stk_printf("solutions/%s/status", c->user); + char *name = stk_printf("solutions/%s/status", c->user); if (rename(fb->name, name) < 0) die("Unable to rename %s to %s: %m", fb->name, name); bclose(fb); @@ -109,27 +156,89 @@ task_unlock_status(struct conn *c, uns write_back) if (fcntl(c->task_lock_fd, F_SETLKW, &fl) < 0) die("Cannot unlock status file: %m"); c->task_lock_fd = 0; - c->task_status = NULL; } struct odes * -task_status_find_task(struct conn *c, struct task *t) +task_status_find_task(struct conn *c, struct task *t, uns create) { for (struct oattr *a = obj_find_attr(c->task_status, 'T' + OBJ_ATTR_SON); a; a=a->same) { struct odes *o = a->son; - byte *name = obj_find_aval(o, 'T'); + char *name = obj_find_aval(o, 'T'); + ASSERT(name); if (!strcmp(name, t->name)) return o; } + if (!create) + return NULL; struct odes *o = obj_add_son(c->task_status, 'T' + OBJ_ATTR_SON); obj_set_attr(o, 'T', t->name); return o; } +struct odes * +task_status_find_part(struct odes *to, char *part, uns create) +{ + for (struct oattr *a = obj_find_attr(to, 'P' + OBJ_ATTR_SON); a; a=a->same) + { + struct odes *o = a->son; + char *name = obj_find_aval(o, 'P'); + ASSERT(name); + if (!strcmp(name, part)) + return o; + } + if (!create) + return NULL; + struct odes *o = obj_add_son(to, 'P' + OBJ_ATTR_SON); + obj_set_attr(o, 'P', part); + return o; +} + +static void +task_record_history(char *user, char *task, char *part, char *ext, uns version, char *submitted_name) +{ + if (!history_format) + return; + + time_t now = time(NULL); + struct tm *tm = localtime(&now); + char prefix[256]; + if (strftime(prefix, sizeof(prefix), history_format, tm) <= 0) + { + msg(L_ERROR, "Error formatting history prefix: too long"); + return; + } + + char *name = stk_printf("%s%s:%s:%s:v%d.%s", prefix, user, task, (strcmp(task, part) ? part : (char*)""), version, ext); + struct fastbuf *orig = bopen(submitted_name, O_RDONLY, 4096); + struct fastbuf *hist = bopen(name, O_WRONLY | O_CREAT | O_EXCL, 4096); + bbcopy_slow(orig, hist, ~0U); + bclose(hist); + bclose(orig); +} + +void +task_submit_part(char *user, char *task, char *part, char *ext, uns version, struct fastbuf *fb) +{ + char *dir = stk_printf("solutions/%s/%s", user, task); + char *name = stk_printf("%s/%s.%s", dir, part, ext); + + struct stat st; + if (stat(dir, &st) < 0 && errno == ENOENT && mkdir(dir, 0777) < 0) + die("Cannot create %s: %m", dir); + + bconfig(fb, BCONFIG_IS_TEMP_FILE, 0); + if (rename(fb->name, name) < 0) + die("Cannot rename %s to %s: %m", fb->name, name); + + task_record_history(user, task, part, ext, version, name); +} + void -task_submit(struct conn *c, struct task *t, struct fastbuf *fb, byte *filename) +task_delete_part(char *user, char *task, char *part, char *ext, uns version UNUSED) { - byte *dir = stk_printf("solutions/%s/%s", c->user, t->name); - byte *name = stk_printf("%s/%s", dir, filename); + char *dir = stk_printf("solutions/%s/%s", user, task); + char *name = stk_printf("%s/%s.%s", dir, part, ext); + if (unlink(name) < 0) + msg(L_ERROR, "Cannot delete %s: %m", name); }