chiark / gitweb /
log rtp timestamp updates (which shows that they are wrong)
[disorder] / server / trackdb.c
index 223dc808c85f2a67457c4b7d5bc52297020d0bb3..324d4774fdc0543f9450a45d2f64a90fca404eea 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * This file is part of DisOrder
- * Copyright (C) 2005, 2006 Richard Kettlewell
+ * Copyright (C) 2005, 2006, 2007 Richard Kettlewell
  *
  * 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
@@ -491,9 +491,12 @@ static char **track_to_words(const char *track,
   struct vector v;
   char **w;
   int nw;
+  const char *rootless = track_rootless(track);
 
+  if(!rootless)
+    rootless = track;                   /* bodge */
   vector_init(&v);
-  if((w = words(casefold(strip_extension(track_rootless(track))), &nw)))
+  if((w = words(casefold(strip_extension(rootless)), &nw)))
     vector_append_many(&v, w, nw);
 
   for(; p; p = p->next)
@@ -578,11 +581,15 @@ static int compute_alias(char **aliasp,
   const char *s = config->alias, *t, *expansion, *part;
   int c, used_db = 0, slash_prefix, err;
   struct kvp *at;
+  const char *const root = find_track_root(track);
 
-  if(strstr(track, "Troggs"))
-    D(("computing alias for %s", track));
+  if(!root) {
+    /* Bodge for tracks with no root */
+    *aliasp = 0;
+    return 0;
+  }
   dynstr_init(&d);
-  dynstr_append_string(&d, find_track_root(track));
+  dynstr_append_string(&d, root);
   while((c = (unsigned char)*s++)) {
     if(c != '{') {
       dynstr_append(&d, c);
@@ -615,20 +622,11 @@ static int compute_alias(char **aliasp,
    * an alias) */
   switch(err = trackdb_getdata(trackdb_tracksdb, d.vec, &at, tid)) {
   case 0:
-    if(strstr(track, "Troggs"))
-      D(("found a hit for alias"));
     if((s = kvp_get(at, "_alias_for"))
        && !strcmp(s, track)) {
     case DB_NOTFOUND:
-      if(strstr(track, "Troggs"))
-        D(("accepting anyway"));
       *aliasp = d.vec;
     } else {
-      if(strstr(track, "Troggs")) {
-        D(("rejecting"));
-        D(("%s", track));
-        D(("%s", s ? s : "(null)"));
-      }
       *aliasp = 0;
     }
     return 0;
@@ -1162,7 +1160,8 @@ static int tag_intersection(char **a, char **b) {
 }
 
 /* Check whether a track is suitable for random play.  Returns 0 if it is,
- * DB_NOTFOUND if it or DB_LOCK_DEADLOCK. */
+ * DB_NOTFOUND if it is not or DB_LOCK_DEADLOCK if the database gave us
+ * that. */
 static int check_suitable(const char *track,
                           DB_TXN *tid,
                           char **required_tags,
@@ -1172,6 +1171,12 @@ static int check_suitable(const char *track,
   struct kvp *p, *t;
   const char *pick_at_random, *played_time;
 
+  /* don't pick tracks that aren't in any surviving collection (for instance
+   * you've edited the config but the rescan hasn't done its job yet) */
+  if(!find_track_root(track)) {
+    info("found track not in any collection: %s", track);
+    return DB_NOTFOUND;
+  }
   /* don't pick aliases - only pick the canonical form */
   if(gettrackdata(track, &t, &p, 0, 0, tid) == DB_LOCK_DEADLOCK)
     return DB_LOCK_DEADLOCK;
@@ -1273,8 +1278,7 @@ const char *trackdb_random(int tries) {
     } else {
       /* No required tags.  We pick random record numbers in the database
        * instead. */
-      switch(err = trackdb_tracksdb->stat(trackdb_tracksdb, tid, &sp,
-                                          DB_RECORDCOUNT)) {
+      switch(err = trackdb_tracksdb->stat(trackdb_tracksdb, tid, &sp, 0)) {
       case 0:
         break;
       case DB_LOCK_DEADLOCK:
@@ -1644,22 +1648,37 @@ int trackdb_scan(const char *root,
                  DB_TXN *tid) {
   DBC *cursor;
   DBT k, d;
-  size_t root_len = strlen(root);
-  int err;
+  const size_t root_len = root ? strlen(root) : 0;
+  int err, cberr;
   struct kvp *data;
+  const char *track;
 
   cursor = trackdb_opencursor(trackdb_tracksdb, tid);
-  err = cursor->c_get(cursor, make_key(&k, root), prepare_data(&d),
-                      DB_SET_RANGE);
+  if(root)
+    err = cursor->c_get(cursor, make_key(&k, root), prepare_data(&d),
+                        DB_SET_RANGE);
+  else {
+    memset(&k, 0, sizeof k);
+    err = cursor->c_get(cursor, &k, prepare_data(&d),
+                        DB_FIRST);
+  }
   while(!err) {
-    if(k.size > root_len
-       && !strncmp(k.data, root, root_len)
-       && ((char *)k.data)[root_len] == '/') {
+    if(!root
+       || (k.size > root_len
+           && !strncmp(k.data, root, root_len)
+           && ((char *)k.data)[root_len] == '/')) {
       data = kvp_urldecode(d.data, d.size);
-      if(kvp_get(data, "_path"))
-        if((err = callback(xstrndup(k.data, k.size), data, u, tid)))
+      if(kvp_get(data, "_path")) {
+        track = xstrndup(k.data, k.size);
+        /* Advance to the next track before the callback so that the callback
+         * may safely delete the track */
+        err = cursor->c_get(cursor, &k, &d, DB_NEXT);
+        if((cberr = callback(track, data, u, tid))) {
+          err = cberr;
           break;
-      err = cursor->c_get(cursor, &k, &d, DB_NEXT);
+        }
+      } else
+        err = cursor->c_get(cursor, &k, &d, DB_NEXT);
     } else
       break;
   }
@@ -1830,4 +1849,3 @@ fill-column:79
 indent-tabs-mode:nil
 End:
 */
-/* arch-tag:/CBQ6uebrasgkefvjc+fHQ */