From: Martin Mares Date: Mon, 4 Jun 2007 09:12:13 +0000 (+0200) Subject: Further bits of submit command. X-Git-Tag: python-dummy-working~405 X-Git-Url: http://mj.ucw.cz/gitweb/?a=commitdiff_plain;h=92811b1aa5a791bc776b58afb241a7d93e737604;p=moe.git Further bits of submit command. --- diff --git a/submit/Makefile b/submit/Makefile index cf9ee31..7866155 100644 --- a/submit/Makefile +++ b/submit/Makefile @@ -6,6 +6,7 @@ LDFLAGS=$(TLSLF) CC=gcc-4.1.1 CFLAGS+=-Wno-pointer-sign -Wdisabled-optimization -Wno-missing-field-initializers +LDFLAGS+=-lpthread # FIXME: Use libucw without threads all: submitd connect diff --git a/submit/commands.c b/submit/commands.c index e583d66..6abd935 100644 --- a/submit/commands.c +++ b/submit/commands.c @@ -72,8 +72,7 @@ write_reply(struct conn *c) else log(L_DEBUG, ">> ???"); } - put_attr_set_type(BUCKET_TYPE_PLAIN); - bput_object(&c->tx_fb, c->reply); + obj_write(&c->tx_fb, c->reply, BUCKET_TYPE_PLAIN); bputc(&c->tx_fb, '\n'); bflush(&c->tx_fb); } @@ -86,6 +85,38 @@ err(struct conn *c, byte *msg) /*** SUBMIT ***/ +static struct fastbuf * +read_attachment(struct conn *c) +{ + uns size = obj_find_anum(c->request, 'S', 0); + if (size > max_attachment_size) + { + err(c, "Submission too large"); + return NULL; + } + obj_set_attr(c->reply, '+', "Go on"); + write_reply(c); + obj_set_attr(c->reply, '+', NULL); + + // This is less efficient than bbcopy(), but we want our own error handling. + struct fastbuf *fb = bopen_tmp(4096); + byte buf[4096]; + uns remains = size; + while (remains) + { + uns cnt = bread(&c->rx_fb, buf, MIN(remains, (uns)sizeof(buf))); + if (!cnt) + { + bclose(fb); + client_error("Truncated attachment"); + } + bwrite(fb, buf, cnt); + remains -= cnt; + } + brewind(fb); + return fb; +} + static void cmd_submit(struct conn *c) { @@ -101,6 +132,19 @@ cmd_submit(struct conn *c) err(c, "No such task"); return; } + struct fastbuf *fb = read_attachment(c); + if (!fb) + return; + + // FIXME: Check contest time + // FIXME: Keep history of submitted tasks + // FIXME: File names + + task_lock_status(c); + struct odes *o = task_status_find_task(c, task); + task_submit(c, task, fb, task->name); + log(L_INFO, "User %s submitted task %s", c->user, task->name); + task_unlock_status(c, 1); } /*** COMMAND MUX ***/ diff --git a/submit/submitd.h b/submit/submitd.h index 9f73326..4030bc3 100644 --- a/submit/submitd.h +++ b/submit/submitd.h @@ -39,6 +39,8 @@ struct conn { struct mempool *pool; struct odes *request; struct odes *reply; + struct odes *task_status; + int task_lock_fd; byte *user; }; @@ -65,5 +67,9 @@ extern struct cf_section tasks_conf; struct task *task_find(byte *name); int user_exists_p(byte *user); +void task_lock_status(struct conn *c); +void task_unlock_status(struct conn *c, uns write_back); +void task_submit(struct conn *c, struct task *t, struct fastbuf *fb, byte *filename); +struct odes *task_status_find_task(struct conn *c, struct task *t); #endif diff --git a/submit/tasks.c b/submit/tasks.c index e420bef..4a69303 100644 --- a/submit/tasks.c +++ b/submit/tasks.c @@ -6,9 +6,13 @@ #include "lib/lib.h" #include "lib/conf.h" +#include "lib/fastbuf.h" #include "lib/stkstring.h" +#include "sherlock/object.h" #include +#include +#include #include "submitd.h" @@ -53,3 +57,79 @@ user_exists_p(byte *user) struct stat st; return !stat(fn, &st) && S_ISREG(st.st_mode); } + +void +task_lock_status(struct conn *c) +{ + ASSERT(!c->task_lock_fd); + if ((c->task_lock_fd = open(stk_printf("solutions/%s/status.lock", c->user), O_RDWR | O_CREAT | O_TRUNC, 0666)) < 0) + die("Cannot create task lock: %m"); + struct flock fl = { + .l_type = F_WRLCK, + .l_whence = SEEK_SET, + .l_start = 0, + .l_len = 1 + }; + 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); + } +} + +void +task_unlock_status(struct conn *c, uns write_back) +{ + ASSERT(c->task_lock_fd); + ASSERT(c->task_status); + + if (write_back) + { + struct fastbuf *fb = bopen_tmp(4096); + 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); + if (rename(fb->name, name) < 0) + die("Unable to rename %s to %s: %m", fb->name, name); + bclose(fb); + } + + struct flock fl = { + .l_type = F_UNLCK, + .l_whence = SEEK_SET, + .l_start = 0, + .l_len = 1 + }; + 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) +{ + 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'); + if (!strcmp(name, t->name)) + return o; + } + struct odes *o = obj_add_son(c->task_status, 'T' + OBJ_ATTR_SON); + obj_set_attr(o, 'T', t->name); + return o; +} + +void +task_submit(struct conn *c, struct task *t, struct fastbuf *fb, byte *filename) +{ + byte *dir = stk_printf("solutions/%s/%s", c->user, t->name); + byte *name = stk_printf("%s/%s", dir, filename); +}