]> mj.ucw.cz Git - moe.git/blobdiff - submit/tasks.c
Updated MO-P admin scripts to new directory layout.
[moe.git] / submit / tasks.c
index 4a6930319799983dae873420da09c8ed5d879174..ecb4cbfc34c925598ec0eebd19ff2bad39373052 100644 (file)
@@ -4,24 +4,45 @@
  *  (c) 2007 Martin Mares <mj@ucw.cz>
  */
 
-#include "lib/lib.h"
-#include "lib/conf.h"
-#include "lib/fastbuf.h"
-#include "lib/stkstring.h"
+#include "ucw/lib.h"
+#include "ucw/conf.h"
+#include "ucw/fastbuf.h"
+#include "ucw/stkstring.h"
+#include "ucw/simple-lists.h"
+#include "ucw/mempool.h"
 #include "sherlock/object.h"
 
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <unistd.h>
+#include <errno.h>
+#include <time.h>
 
 #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);
 }