]> mj.ucw.cz Git - eval.git/commitdiff
Further bits of submit command.
authorMartin Mares <mj@ucw.cz>
Mon, 4 Jun 2007 09:12:13 +0000 (11:12 +0200)
committerMartin Mares <mj@ucw.cz>
Mon, 4 Jun 2007 09:12:13 +0000 (11:12 +0200)
submit/Makefile
submit/commands.c
submit/submitd.h
submit/tasks.c

index cf9ee31473e8d49cbba3bb94bb98b783c904cfde..7866155972f22fd6e6d3d98a8613a8a0d4179500 100644 (file)
@@ -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
 
index e583d66a518ec97d477cc8afd6b1ce348372f129..6abd935f0f30cd9f3bbf4ed2d491b74df1e4ae16 100644 (file)
@@ -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 ***/
index 9f73326730460e904645c65ef7ea10c3310a39b9..4030bc31e67f7c731490aa365a9f1df148775633 100644 (file)
@@ -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
index e420bef392ad7ce7faab6a54f9fed0b2842c2625..4a6930319799983dae873420da09c8ed5d879174 100644 (file)
@@ -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 <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
 
 #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);
+}