X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/disorder/blobdiff_plain/460b9539a7c15580e41a71bbc0f47ae776238915..d8653a539ff8aa8f3b27dd74fcd9cecde0ed5d86:/server/trackdb.c diff --git a/server/trackdb.c b/server/trackdb.c index 223dc80..fabb203 100644 --- a/server/trackdb.c +++ b/server/trackdb.c @@ -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; @@ -962,6 +960,10 @@ int trackdb_set(const char *track, int err, cmp; char *oldalias, *newalias, **oldtags = 0, **newtags; + if(value) { + /* TODO: if value matches default then set value=0 */ + } + for(;;) { tid = trackdb_begin_transaction(); if((err = gettrackdata(track, &t, &p, 0, @@ -1162,7 +1164,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 +1175,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 +1282,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 +1652,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 +1853,3 @@ fill-column:79 indent-tabs-mode:nil End: */ -/* arch-tag:/CBQ6uebrasgkefvjc+fHQ */