chiark / gitweb /
log rtp timestamp updates (which shows that they are wrong)
[disorder] / server / trackdb.c
index be1aea417a7bd6be6edc681ded10986e4d8567ab..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,9 +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(!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);
@@ -1269,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:
@@ -1640,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;
   }