chiark / gitweb /
Merge from dmanual branch
[disorder] / server / schedule.c
index c2cdb6d4ce352ebd403347cc18f82626db25662c..f1b20a123d96433188d70bef0286f60fcf8406c5 100644 (file)
@@ -2,20 +2,18 @@
  * This file is part of DisOrder
  * Copyright (C) 2008 Richard Kettlewell
  *
- * This program is free software; you can redistribute it and/or modify
+ * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * the Free Software Foundation, either version 3 of the License, or
  * (at your option) any later version.
  *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
 /** @file server/schedule.c
  *
  * TODO: add disorder-dump support
  */
-
-#include <config.h>
-#include "types.h"
-
-#include <string.h>
-#include <db.h>
-#include <time.h>
-#include <stddef.h>
-
-#include "trackdb.h"
-#include "trackdb-int.h"
-#include "schedule.h"
-#include "table.h"
-#include "kvp.h"
-#include "log.h"
-#include "queue.h"
-#include "server-queue.h"
-#include "state.h"
-#include "play.h"
-#include "mem.h"
-#include "random.h"
-#include "vector.h"
+#include "disorder-server.h"
 
 static int schedule_trigger(ev_source *ev,
                            const struct timeval *now,
@@ -118,6 +95,9 @@ static const char *const schedule_required[] = {"when", "who", "action"};
 
 /** @brief Parse a scheduled event key and data
  * @param k Pointer to key
+ * @param d Pointer to data
+ * @param idp Where to store event ID
+ * @param actiondatap Where to store parsed data
  * @param whenp Where to store timestamp
  * @return 0 on success, non-0 on error
  *
@@ -134,7 +114,8 @@ static int schedule_parse(const DBT *k,
 
   /* Reject bogus keys */
   if(!k->size || k->size > 128) {
-    error(0, "bogus schedule.db key (%lu bytes)", (unsigned long)k->size);
+    disorder_error(0, "bogus schedule.db key (%lu bytes)",
+                   (unsigned long)k->size);
     return -1;
   }
   id = xstrndup(k->data, k->size);
@@ -142,8 +123,8 @@ static int schedule_parse(const DBT *k,
   /* Reject items without the required fields */
   for(n = 0; n < NREQUIRED; ++n) {
     if(!kvp_get(actiondata, schedule_required[n])) {
-      error(0, "scheduled event %s: missing required field '%s'",
-           id, schedule_required[n]);
+      disorder_error(0, "scheduled event %s: missing required field '%s'",
+                     id, schedule_required[n]);
       return -1;
     }
   }
@@ -166,10 +147,10 @@ static int cdel(DBC *cursor) {
   case 0:
     break;
   case DB_LOCK_DEADLOCK:
-    error(0, "error deleting from schedule.db: %s", db_strerror(err));
+    disorder_error(0, "error deleting from schedule.db: %s", db_strerror(err));
     break;
   default:
-    fatal(0, "error deleting from schedule.db: %s", db_strerror(err));
+    disorder_fatal(0, "error deleting from schedule.db: %s", db_strerror(err));
   }
   return err;
 }
@@ -202,12 +183,13 @@ static int schedule_init_tid(ev_source *ev,
     }
     when.tv_usec = 0;
     /* The action might be in the past */
-    if(when.tv_sec < time(0)) {
+    if(when.tv_sec < xtime(0)) {
       const char *priority = kvp_get(actiondata, "priority");
 
       if(priority && !strcmp(priority, "junk")) {
         /* Junk actions that are in the past are discarded during startup */
        /* TODO recurring events should be handled differently here */
+        disorder_info("junk event %s is in the past, discarding", id);
        if(cdel(cursor))
          goto deadlocked;
         /* Skip this time */
@@ -222,10 +204,10 @@ static int schedule_init_tid(ev_source *ev,
     err = 0;
     break;
   case DB_LOCK_DEADLOCK:
-    error(0, "error querying schedule.db: %s", db_strerror(err));
+    disorder_error(0, "error querying schedule.db: %s", db_strerror(err));
     break;
   default:
-    fatal(0, "error querying schedule.db: %s", db_strerror(err));
+    disorder_fatal(0, "error querying schedule.db: %s", db_strerror(err));
   }
 deadlocked:
   if(trackdb_closecursor(cursor))
@@ -247,8 +229,9 @@ void schedule_init(ev_source *ev) {
 /******************************************************************************/
 
 /** @brief Create a scheduled event
- * @param ev Event loop
+ * @param id Event ID
  * @param actiondata Action data
+ * @param tid Containing transaction
  */
 static int schedule_add_tid(const char *id,
                            struct kvp *actiondata,
@@ -265,12 +248,12 @@ static int schedule_add_tid(const char *id,
   case 0:
     break;
   case DB_LOCK_DEADLOCK:
-    error(0, "error updating schedule.db: %s", db_strerror(err));
+    disorder_error(0, "error updating schedule.db: %s", db_strerror(err));
     return err;
   case DB_KEYEXIST:
     return err;
   default:
-    fatal(0, "error updating schedule.db: %s", db_strerror(err));
+    disorder_fatal(0, "error updating schedule.db: %s", db_strerror(err));
   }
   return 0;
 }
@@ -294,8 +277,8 @@ const char *schedule_add(ev_source *ev,
   /* Check that the required field are present */
   for(n = 0; n < NREQUIRED; ++n) {
     if(!kvp_get(actiondata, schedule_required[n])) {
-      error(0, "new scheduled event is missing required field '%s'",
-           schedule_required[n]);
+      disorder_error(0, "new scheduled event is missing required field '%s'",
+                     schedule_required[n]);
       return 0;
     }
   }
@@ -305,8 +288,8 @@ const char *schedule_add(ev_source *ev,
   when.tv_sec = atoll(kvp_get(actiondata, "when"));
   when.tv_usec = 0;
   /* Reject events in the past */
-  if(when.tv_sec <= time(0)) {
-    error(0, "new scheduled event is in the past");
+  if(when.tv_sec <= xtime(0)) {
+    disorder_error(0, "new scheduled event is in the past");
     return 0;
   }
   do {
@@ -331,8 +314,8 @@ struct kvp *schedule_get(const char *id) {
   /* Check that the required field are present */
   for(n = 0; n < NREQUIRED; ++n) {
     if(!kvp_get(actiondata, schedule_required[n])) {
-      error(0, "scheduled event %s is missing required field '%s'",
-           id, schedule_required[n]);
+      disorder_error(0, "scheduled event %s is missing required field '%s'",
+                     id, schedule_required[n]);
       return 0;
     }
   }
@@ -380,19 +363,19 @@ static void schedule_play(ev_source *ev,
 
   /* This stuff has rather a lot in common with c_play() */
   if(!track) {
-    error(0, "scheduled event %s: no track field", id);
+    disorder_error(0, "scheduled event %s: no track field", id);
     return;
   }
   if(!trackdb_exists(track)) {
-    error(0, "scheduled event %s: no such track as %s", id, track);
+    disorder_error(0, "scheduled event %s: no such track as %s", id, track);
     return;
   }
   if(!(track = trackdb_resolve(track))) {
-    error(0, "scheduled event %s: cannot resolve track %s", id, track);
+    disorder_error(0, "scheduled event %s: cannot resolve track %s", id, track);
     return;
   }
-  info("scheduled event %s: %s play %s", id,  who, track);
-  q = queue_add(track, who, WHERE_START);
+  disorder_info("scheduled event %s: %s play %s", id,  who, track);
+  q = queue_add(track, who, WHERE_START, NULL, origin_scheduled);
   queue_write();
   if(q == qhead.next && playing)
     prepare(ev, q);
@@ -407,18 +390,19 @@ static void schedule_set_global(ev_source attribute((unused)) *ev,
   const char *value = kvp_get(actiondata, "value");
 
   if(!key) {
-    error(0, "scheduled event %s: no key field", id);
+    disorder_error(0, "scheduled event %s: no key field", id);
     return;
   }
   if(key[0] == '_') {
-    error(0, "scheduled event %s: cannot set internal global preferences (%s)",
-         id, key);
+    disorder_error(0, "scheduled event %s: cannot set internal global preferences (%s)",
+                   id, key);
     return;
   }
   if(value)
-    info("scheduled event %s: %s set-global %s=%s", id, who, key, value);
+    disorder_info("scheduled event %s: %s set-global %s=%s",
+                  id, who, key, value);
   else
-    info("scheduled event %s: %s set-global %s unset", id,  who, key);
+    disorder_info("scheduled event %s: %s set-global %s unset", id,  who, key);
   trackdb_set_global(key, value, who);
 }
 
@@ -438,6 +422,7 @@ static struct {
 };
 
 /** @brief Look up a scheduled event
+ * @param id Event ID
  * @param actiondata Event description
  * @return index in schedule_actions[] on success, -1 on error
  *
@@ -453,29 +438,30 @@ static int schedule_lookup(const char *id,
   int n;
 
   /* Look up the action */
-  n = TABLE_FIND(schedule_actions, typeof(schedule_actions[0]), name, action);
+  n = TABLE_FIND(schedule_actions, name, action);
   if(n < 0) {
-    error(0, "scheduled event %s: unrecognized action '%s'", id, action);
+    disorder_error(0, "scheduled event %s: unrecognized action '%s'",
+                   id, action);
     return -1;
   }
   /* Find the user */
   if(!(userinfo = trackdb_getuserinfo(who))) {
-    error(0, "scheduled event %s: user '%s' does not exist", id, who);
+    disorder_error(0, "scheduled event %s: user '%s' does not exist", id, who);
     return -1;
   }
   /* Check that they have suitable rights */
   if(!(rights = kvp_get(userinfo, "rights"))) {
-    error(0, "scheduled event %s: user %s' has no rights???", id, who);
+    disorder_error(0, "scheduled event %s: user %s' has no rights???", id, who);
     return -1;
   }
   if(parse_rights(rights, &r, 1)) {
-    error(0, "scheduled event %s: user %s has invalid rights '%s'",
-         id, who, rights);
+    disorder_error(0, "scheduled event %s: user %s has invalid rights '%s'",
+                   id, who, rights);
     return -1;
   }
   if(!(r & schedule_actions[n].right)) {
-    error(0, "scheduled event %s: user %s lacks rights for action %s",
-         id, who, action);
+    disorder_error(0, "scheduled event %s: user %s lacks rights for action %s",
+                   id, who, action);
     return -1;
   }
   return n;