X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/disorder/blobdiff_plain/dd9af5cb6877b3c6c6b33d99800ec35745272729..cca956b199841d754e8a78391d2e2c7efce4a3ee:/lib/trackdb.c diff --git a/lib/trackdb.c b/lib/trackdb.c index 2080e63..4009358 100644 --- a/lib/trackdb.c +++ b/lib/trackdb.c @@ -23,15 +23,11 @@ * This file is getting in desparate need of splitting up... */ -#include -#include "types.h" +#include "common.h" -#include -#include #include #include #include -#include #include #include #include @@ -39,7 +35,6 @@ #include #include #include -#include #include #include #include @@ -145,6 +140,17 @@ DB *trackdb_globaldb; /* global preferences */ */ DB *trackdb_noticeddb; /* when track noticed */ +/** @brief The schedule database + * + * - Keys are ID strings, generated at random + * - Values are encoded key-value pairs + * - There can be more than one value per key + * - Data cannot be reconstructed + * + * See @ref server/schedule.c for further information. + */ +DB *trackdb_scheduledb; + /** @brief The user database * - Keys are usernames * - Values are encoded key-value pairs @@ -460,6 +466,7 @@ void trackdb_open(int flags) { trackdb_globaldb = open_db("global.db", 0, DB_HASH, dbflags, 0666); trackdb_noticeddb = open_db("noticed.db", DB_DUPSORT, DB_BTREE, dbflags, 0666); + trackdb_scheduledb = open_db("schedule.db", 0, DB_HASH, dbflags, 0666); if(!trackdb_existing_database) { /* Stash the database version */ char buf[32]; @@ -490,6 +497,8 @@ void trackdb_close(void) { fatal(0, "error closing global.db: %s", db_strerror(err)); if((err = trackdb_noticeddb->close(trackdb_noticeddb, 0))) fatal(0, "error closing noticed.db: %s", db_strerror(err)); + if((err = trackdb_scheduledb->close(trackdb_scheduledb, 0))) + fatal(0, "error closing schedule.db: %s", db_strerror(err)); if((err = trackdb_usersdb->close(trackdb_usersdb, 0))) fatal(0, "error closing users.db: %s", db_strerror(err)); trackdb_tracksdb = trackdb_searchdb = trackdb_prefsdb = 0; @@ -1387,6 +1396,60 @@ void trackdb_stats_subprocess(ev_source *ev, ev_reader_new(ev, p[0], stats_read, stats_error, d, "disorder-stats reader"); } +/** @brief Parse a track name part preference + * @param name Preference name + * @param partp Where to store part name + * @param contextp Where to store context name + * @return 0 on success, non-0 if parse fails + */ +static int trackdb__parse_namepref(const char *name, + char **partp, + char **contextp) { + char *c; + static const char prefix[] = "trackname_"; + + if(strncmp(name, prefix, strlen(prefix))) + return -1; /* not trackname_* at all */ + name += strlen(prefix); + /* There had better be a _ between context and part */ + c = strchr(name, '_'); + if(!c) + return -1; + /* Context is first in the pref name even though most APIs have the part + * first. Confusing; sorry. */ + *contextp = xstrndup(name, c - name); + ++c; + /* There had better NOT be a second _ */ + if(strchr(c, '_')) + return -1; + *partp = xstrdup(c); + return 0; +} + +/** @brief Compute the default value for a track preference + * @param track Track name + * @param name Preference name + * @return Default value or 0 if none/not known + */ +static const char *trackdb__default(const char *track, const char *name) { + char *context, *part; + + if(!trackdb__parse_namepref(name, &part, &context)) { + /* We can work out the default for a trackname_ pref */ + return trackname_part(track, context, part); + } else if(!strcmp(name, "weight")) { + /* We know the default weight */ + return "90000"; + } else if(!strcmp(name, "pick_at_random")) { + /* By default everything is eligible for picking at random */ + return "1"; + } else if(!strcmp(name, "tags")) { + /* By default everything no track has any tags */ + return ""; + } + return 0; +} + /* set a pref (remove if value=0) */ int trackdb_set(const char *track, const char *name, @@ -1395,9 +1458,15 @@ int trackdb_set(const char *track, DB_TXN *tid; int err, cmp; char *oldalias, *newalias, **oldtags = 0, **newtags; + const char *def; + /* If the value matches the default then unset instead, to keep the database + * tidy. Older versions did not have this feature so your database may yet + * have some default values stored in it. */ if(value) { - /* TODO: if value matches default then set value=0 */ + def = trackdb__default(track, name); + if(def && !strcmp(value, def)) + value = 0; } for(;;) { @@ -2135,7 +2204,7 @@ static int reap_rescan(ev_source attribute((unused)) *ev, eventlog("rescanned", (char *)0); /* Call rescanned callbacks */ while(rescanned_list) { - void (*rescanned)(void *u) = rescanned_list->rescanned; + void (*rescanned)(void *u_) = rescanned_list->rescanned; void *ru = rescanned_list->ru; rescanned_list = rescanned_list->next;