chiark / gitweb /
More memory hygeine
[disorder] / lib / trackdb.c
1 /*
2  * This file is part of DisOrder
3  * Copyright (C) 2005-2008 Richard Kettlewell
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  * 
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  * 
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 /** @file lib/trackdb.c
19  * @brief Track database
20  *
21  * This file is getting in desparate need of splitting up...
22  */
23
24 #include "common.h"
25
26 #include <db.h>
27 #include <sys/socket.h>
28 #include <pcre.h>
29 #include <unistd.h>
30 #include <errno.h>
31 #include <stddef.h>
32 #include <sys/time.h>
33 #include <sys/resource.h>
34 #include <time.h>
35 #include <arpa/inet.h>
36 #include <dirent.h>
37 #include <sys/stat.h>
38 #include <gcrypt.h>
39
40 #include "event.h"
41 #include "mem.h"
42 #include "kvp.h"
43 #include "log.h"
44 #include "vector.h"
45 #include "rights.h"
46 #include "trackdb.h"
47 #include "configuration.h"
48 #include "syscalls.h"
49 #include "wstat.h"
50 #include "printf.h"
51 #include "filepart.h"
52 #include "trackname.h"
53 #include "trackdb-int.h"
54 #include "logfd.h"
55 #include "cache.h"
56 #include "eventlog.h"
57 #include "hash.h"
58 #include "unicode.h"
59 #include "unidata.h"
60 #include "base64.h"
61 #include "sendmail.h"
62
63 #define RESCAN "disorder-rescan"
64 #define DEADLOCK "disorder-deadlock"
65
66 static const char *getpart(const char *track,
67                            const char *context,
68                            const char *part,
69                            const struct kvp *p,
70                            int *used_db);
71 static char **trackdb_new_tid(int *ntracksp,
72                               int maxtracks,
73                               DB_TXN *tid);
74 static int trackdb_expire_noticed_tid(time_t earliest, DB_TXN *tid);
75 static char *normalize_tag(const char *s, size_t ns);
76
77 const struct cache_type cache_files_type = { 86400 };
78 unsigned long cache_files_hits, cache_files_misses;
79
80 /** @brief Set by trackdb_open() */
81 int trackdb_existing_database;
82
83 /* setup and teardown ********************************************************/
84
85 /** @brief Database home directory
86  *
87  * All database files live below here.  It had better never change.
88  */
89 static const char *home;
90
91 /** @brief Database environment */
92 DB_ENV *trackdb_env;
93
94 /** @brief The tracks database
95  * - Keys are UTF-8(NFC(unicode(path name)))
96  * - Values are encoded key-value pairs
97  * - Data is reconstructable data about tracks that currently exist
98  */
99 DB *trackdb_tracksdb;
100
101 /** @brief The preferences database
102  *
103  * - Keys are UTF-8(NFC(unicode(path name)))
104  * - Values are encoded key-value pairs
105  * - Data is user data about tracks (that might not exist any more)
106  * and cannot be reconstructed
107  */
108 DB *trackdb_prefsdb;
109
110 /** @brief The search database
111  *
112  * - Keys are UTF-8(NFKC(casefold(search term)))
113  * - Values are UTF-8(NFC(unicode(path name)))
114  * - There can be more than one value per key
115  * - Presence of key,value means that path matches the search terms
116  * - Only tracks fond in @ref trackdb_tracksdb are represented here
117  * - This database can be reconstructed, it contains no user data
118  */
119 DB *trackdb_searchdb;
120
121 /** @brief The tags database
122  *
123  * - Keys are UTF-8(NFKC(casefold(tag)))
124  * - Values are UTF-8(NFC(unicode(path name)))
125  * - There can be more than one value per key
126  * - Presence of key,value means that path matches the tag
127  * - This is always in sync with the tags preference
128  * - This database can be reconstructed, it contains no user data
129  */
130 DB *trackdb_tagsdb;                     /* the tags database */
131
132 /** @brief The global preferences database
133  * - Keys are UTF-8(NFC(preference))
134  * - Values are global preference values
135  * - Data is user data and cannot be reconstructed
136  */
137 DB *trackdb_globaldb;                   /* global preferences */
138
139 /** @brief The noticed database
140  * - Keys are 64-bit big-endian timestamps
141  * - Values are UTF-8(NFC(unicode(path name)))
142  * - There can be more than one value per key
143  * - Presence of key,value means that path was added at the given time
144  * - Data cannot be reconstructed (but isn't THAT important)
145  */
146 DB *trackdb_noticeddb;                   /* when track noticed */
147
148 /** @brief The schedule database
149  *
150  * - Keys are ID strings, generated at random
151  * - Values are encoded key-value pairs
152  * - There can be more than one value per key
153  * - Data cannot be reconstructed
154  *
155  * See @ref server/schedule.c for further information.
156  */
157 DB *trackdb_scheduledb;
158
159 /** @brief The user database
160  * - Keys are usernames
161  * - Values are encoded key-value pairs
162  * - Data is user data and cannot be reconstructed
163  */
164 DB *trackdb_usersdb;
165
166 /** @brief The playlists database
167  * - Keys are playlist names
168  * - Values are encoded key-value pairs
169  * - Data is user data and cannot be reconstructed
170  */
171 DB *trackdb_playlistsdb;
172
173 /** @brief Deadlock manager PID */
174 static pid_t db_deadlock_pid = -1;
175
176 /** @brief Rescanner PID */
177 static pid_t rescan_pid = -1;
178
179 /** @brief Set when the database environment exists */
180 static int initialized;
181
182 /** @brief Set when databases are open */
183 static int opened;
184
185 /** @brief Current stats subprocess PIDs */
186 static hash *stats_pids;
187
188 /** @brief PID of current random track chooser (disorder-choose) */
189 static pid_t choose_pid = -1;
190
191 /** @brief Our end of pipe from disorder-choose */
192 static int choose_fd;
193
194 /** @brief Callback to supply random track to */
195 static random_callback *choose_callback;
196
197 /** @brief Accumulator for output from disorder-choose */
198 static struct dynstr choose_output;
199
200 /** @brief Current completion status of disorder-choose
201  * A bitmap of @ref CHOOSE_READING and @ref CHOOSE_RUNNING.
202  */
203 static unsigned choose_complete;
204
205 /* @brief Exit status from disorder-choose */
206 static int choose_status;
207
208 /** @brief disorder-choose process is running */
209 #define CHOOSE_RUNNING 1
210
211 /** @brief disorder-choose pipe is still open */
212 #define CHOOSE_READING 2
213
214 /** @brief Comparison function for filename-based keys */
215 static int compare(DB attribute((unused)) *db_,
216                    const DBT *a, const DBT *b) {
217   return compare_path_raw(a->data, a->size, b->data, b->size);
218 }
219
220 /** @brief Test whether the track database can be read
221  * @return 1 if it can, 0 if it cannot
222  */
223 int trackdb_readable(void) {
224   char *usersdb;
225
226   byte_xasprintf(&usersdb, "%s/users.db", config->home);
227   return access(usersdb, R_OK) == 0;
228 }
229
230 /** @brief Open database environment
231  * @param flags Flags word
232  *
233  * Flags should be one of:
234  * - @ref TRACKDB_NO_RECOVER
235  * - @ref TRACKDB_NORMAL_RECOVER
236  * - @ref TRACKDB_FATAL_RECOVER
237  * - @ref TRACKDB_MAY_CREATE
238  */
239 void trackdb_init(int flags) {
240   int err;
241   const int recover = flags & TRACKDB_RECOVER_MASK;
242   static int recover_type[] = { 0, DB_RECOVER, DB_RECOVER_FATAL };
243
244   /* sanity checks */
245   assert(initialized == 0);
246   ++initialized;
247   if(home) {
248     if(strcmp(home, config->home))
249       disorder_fatal(0, "cannot change db home without server restart");
250     home = config->home;
251   }
252
253   if(flags & TRACKDB_MAY_CREATE) {
254     DIR *dp;
255     struct dirent *de;
256     struct stat st;
257     char *p;
258
259     /* Remove world/group permissions on any regular files already in the
260      * database directory.  Actually we don't care about all of them but it's
261      * easier to just do the lot.  This can be revisited if it's a serious
262      * practical inconvenience for anyone.
263      *
264      * The socket, not being a regular file, is excepted.
265      */
266     if(!(dp = opendir(config->home)))
267       disorder_fatal(errno, "error reading %s", config->home);
268     while((de = readdir(dp))) {
269       byte_xasprintf(&p, "%s/%s", config->home, de->d_name);
270       if(lstat(p, &st) == 0
271          && S_ISREG(st.st_mode)
272          && (st.st_mode & 077)) {
273         if(chmod(p, st.st_mode & 07700) < 0)
274           disorder_fatal(errno, "cannot chmod %s", p);
275       }
276       xfree(p);
277     }
278     closedir(dp);
279   }
280
281   /* create environment */
282   if((err = db_env_create(&trackdb_env, 0)))
283     disorder_fatal(0, "db_env_create: %s", db_strerror(err));
284   if((err = trackdb_env->set_alloc(trackdb_env,
285                                    xmalloc_noptr, xrealloc_noptr, xfree)))
286     disorder_fatal(0, "trackdb_env->set_alloc: %s", db_strerror(err));
287   if((err = trackdb_env->set_lk_max_locks(trackdb_env, 10000)))
288     disorder_fatal(0, "trackdb_env->set_lk_max_locks: %s", db_strerror(err));
289   if((err = trackdb_env->set_lk_max_objects(trackdb_env, 10000)))
290     disorder_fatal(0, "trackdb_env->set_lk_max_objects: %s", db_strerror(err));
291   if((err = trackdb_env->open(trackdb_env, config->home,
292                               DB_INIT_LOG
293                               |DB_INIT_LOCK
294                               |DB_INIT_MPOOL
295                               |DB_INIT_TXN
296                               |DB_CREATE
297                               |recover_type[recover],
298                               0600)))
299     disorder_fatal(0, "trackdb_env->open %s: %s",
300                    config->home, db_strerror(err));
301   trackdb_env->set_errpfx(trackdb_env, "DB");
302   trackdb_env->set_errfile(trackdb_env, stderr);
303   trackdb_env->set_verbose(trackdb_env, DB_VERB_DEADLOCK, 1);
304   trackdb_env->set_verbose(trackdb_env, DB_VERB_RECOVERY, 1);
305   trackdb_env->set_verbose(trackdb_env, DB_VERB_REPLICATION, 1);
306   D(("initialized database environment"));
307 }
308
309 /** @brief Called when deadlock manager terminates */
310 static int reap_db_deadlock(ev_source attribute((unused)) *ev,
311                             pid_t attribute((unused)) pid,
312                             int status,
313                             const struct rusage attribute((unused)) *rusage,
314                             void attribute((unused)) *u) {
315   db_deadlock_pid = -1;
316   if(initialized)
317     disorder_fatal(0, "deadlock manager unexpectedly terminated: %s",
318                    wstat(status));
319   else
320     D(("deadlock manager terminated: %s", wstat(status)));
321   return 0;
322 }
323
324 /** @brief Start a subprogram
325  * @param ev Event loop
326  * @param outputfd File descriptor to redirect @c stdout to, or -1
327  * @param prog Program name
328  * @param ... Arguments
329  * @return PID
330  *
331  * Starts a subprocess.  Adds the following arguments:
332  * - @c --config to ensure the right config file is used
333  * - @c --debug or @c --no-debug to match debug settings
334  * - @c --syslog or @c --no-syslog to match log settings
335  */
336 static pid_t subprogram(ev_source *ev, int outputfd, const char *prog,
337                         ...) {
338   pid_t pid;
339   va_list ap;
340   const char *args[1024], **argp, *a;
341
342   argp = args;
343   *argp++ = prog;
344   *argp++ = "--config";
345   *argp++ = configfile;
346   *argp++ = debugging ? "--debug" : "--no-debug";
347   *argp++ = log_default == &log_syslog ? "--syslog" : "--no-syslog";
348   va_start(ap, prog);
349   while((a = va_arg(ap, const char *)))
350     *argp++ = a;
351   va_end(ap);
352   *argp = 0;
353   /* If we're in the background then trap subprocess stdout/stderr */
354   if(!(pid = xfork())) {
355     exitfn = _exit;
356     if(ev)
357       ev_signal_atfork(ev);
358     signal(SIGPIPE, SIG_DFL);
359     if(outputfd != -1) {
360       xdup2(outputfd, 1);
361       xclose(outputfd);
362     }
363     /* ensure we don't leak privilege anywhere */
364     if(setuid(geteuid()) < 0)
365       disorder_fatal(errno, "error calling setuid");
366     /* If we were negatively niced, undo it.  We don't bother checking for 
367     * error, it's not that important. */
368     setpriority(PRIO_PROCESS, 0, 0);
369     execvp(prog, (char **)args);
370     disorder_fatal(errno, "error invoking %s", prog);
371   }
372   return pid;
373 }
374
375 /** @brief Start deadlock manager
376  * @param ev Event loop
377  *
378  * Called from the main server (only).
379  */
380 void trackdb_master(ev_source *ev) {
381   assert(db_deadlock_pid == -1);
382   db_deadlock_pid = subprogram(ev, -1, DEADLOCK, (char *)0);
383   ev_child(ev, db_deadlock_pid, 0, reap_db_deadlock, 0);
384   D(("started deadlock manager"));
385 }
386
387 /** @brief Kill a subprocess and wait for it to terminate
388  * @param ev Event loop or NULL
389  * @param pid Process ID or -1
390  * @param what Description of subprocess
391  *
392  * Used during trackdb_deinit().  This function blocks so don't use it for
393  * normal teardown as that will hang the server.
394  */
395 static void terminate_and_wait(ev_source *ev,
396                                pid_t pid,
397                                const char *what) {
398   int err;
399
400   if(pid == -1)
401     return;
402   if(kill(pid, SIGTERM) < 0)
403     disorder_fatal(errno, "error killing %s", what);
404   /* wait for the rescanner to finish */
405   while(waitpid(pid, &err, 0) == -1 && errno == EINTR)
406     ;
407   if(ev)
408     ev_child_cancel(ev, pid);
409 }
410
411 /** @brief Close database environment
412  * @param ev Event loop
413  */
414 void trackdb_deinit(ev_source *ev) {
415   int err;
416
417   /* sanity checks */
418   assert(initialized == 1);
419   --initialized;
420
421   /* close the environment */
422   if((err = trackdb_env->close(trackdb_env, 0)))
423     disorder_fatal(0, "trackdb_env->close: %s", db_strerror(err));
424
425   terminate_and_wait(ev, rescan_pid, "disorder-rescan");
426   rescan_pid = -1;
427   terminate_and_wait(ev, choose_pid, "disorder-choose");
428   choose_pid = -1;
429
430   if(stats_pids) {
431     char **ks = hash_keys(stats_pids);
432
433     while(*ks) {
434       pid_t pid = atoi(*ks++);
435       terminate_and_wait(ev, pid, "disorder-stats");
436     }
437     stats_pids = NULL;
438   }
439
440   terminate_and_wait(ev, db_deadlock_pid, "disorder-deadlock");
441   db_deadlock_pid = -1;
442   D(("deinitialized database environment"));
443 }
444
445 /** @brief Open a specific database
446  * @param path Relative path to database
447  * @param dbflags Database flags: DB_DUP, DB_DUPSORT, etc
448  * @param dbtype Database type: DB_HASH, DB_BTREE, etc
449  * @param openflags Open flags: DB_RDONLY, DB_CREATE, etc
450  * @param mode Permission mask: usually 0666
451  * @return Database handle
452  */
453 static DB *open_db(const char *path,
454                    u_int32_t dbflags,
455                    DBTYPE dbtype,
456                    u_int32_t openflags,
457                    int mode) {
458   int err, err2;
459   DB *db;
460
461   D(("open %s", path));
462   path = config_get_file(path);
463   if((err = db_create(&db, trackdb_env, 0)))
464     disorder_fatal(0, "db_create %s: %s", path, db_strerror(err));
465   if(dbflags)
466     if((err = db->set_flags(db, dbflags)))
467       disorder_fatal(0, "db->set_flags %s: %s", path, db_strerror(err));
468   if(dbtype == DB_BTREE)
469     if((err = db->set_bt_compare(db, compare)))
470       disorder_fatal(0, "db->set_bt_compare %s: %s", path, db_strerror(err));
471   if((err = db->open(db, 0, path, 0, dbtype,
472                      openflags | DB_AUTO_COMMIT, mode))) {
473     if((openflags & DB_CREATE) || errno != ENOENT) {
474       if((err2 = db->close(db, 0)))
475         disorder_error(0, "db->close: %s", db_strerror(err2));
476       trackdb_close();
477       trackdb_env->close(trackdb_env,0);
478       trackdb_env = 0;
479       disorder_fatal(0, "db->open %s: %s", path, db_strerror(err));
480     }
481     db->close(db, 0);
482     db = 0;
483   }
484   return db;
485 }
486
487 /** @brief Open track databases
488  * @param flags Flags flags word
489  *
490  * @p flags should have one of:
491  * - @p TRACKDB_NO_UPGRADE, if no upgrade should be attempted
492  * - @p TRACKDB_CAN_UPGRADE, if an upgrade may be attempted
493  * - @p TRACKDB_OPEN_FOR_UPGRADE, if this is disorder-dbupgrade
494  * Also it may have:
495  * - @p TRACKDB_READ_ONLY, read only access
496  */
497 void trackdb_open(int flags) {
498   int err;
499   pid_t pid;
500   uint32_t dbflags = flags & TRACKDB_READ_ONLY ? DB_RDONLY : DB_CREATE;
501
502   /* sanity checks */
503   assert(opened == 0);
504   ++opened;
505   /* check the database version first */
506   trackdb_globaldb = open_db("global.db", 0, DB_HASH, DB_RDONLY, 0666);
507   if(trackdb_globaldb) {
508     /* This is an existing database */
509     const char *s;
510     long oldversion;
511
512     s = trackdb_get_global("_dbversion");
513     /* Close the database again,  we'll open it property below */
514     if((err = trackdb_globaldb->close(trackdb_globaldb, 0)))
515       disorder_fatal(0, "error closing global.db: %s", db_strerror(err));
516     trackdb_globaldb = 0;
517     /* Convert version string to an integer */
518     oldversion = s ? atol(s) : 1;
519     if(oldversion > config->dbversion) {
520       /* Database is from the future; we never allow this. */
521       disorder_fatal(0, "this version of DisOrder is too old for database version %ld",
522                      oldversion);
523     }
524     if(oldversion < config->dbversion) {
525       /* Database version is out of date */
526       switch(flags & TRACKDB_UPGRADE_MASK) {
527       case TRACKDB_NO_UPGRADE:
528         /* This database needs upgrading but this is not permitted */
529         disorder_fatal(0, "database needs upgrading from %ld to %ld",
530                        oldversion, config->dbversion);
531       case TRACKDB_CAN_UPGRADE:
532         /* This database needs upgrading */
533         disorder_info("invoking disorder-dbupgrade to upgrade from %ld to %ld",
534              oldversion, config->dbversion);
535         pid = subprogram(0, -1, "disorder-dbupgrade", (char *)0);
536         while(waitpid(pid, &err, 0) == -1 && errno == EINTR)
537           ;
538         if(err)
539           disorder_fatal(0, "disorder-dbupgrade %s", wstat(err));
540         disorder_info("disorder-dbupgrade succeeded");
541         break;
542       case TRACKDB_OPEN_FOR_UPGRADE:
543         break;
544       default:
545         abort();
546       }
547     }
548     if(oldversion == config->dbversion && (flags & TRACKDB_OPEN_FOR_UPGRADE)) {
549       /* This doesn't make any sense */
550       disorder_fatal(0, "database is already at current version");
551     }
552     trackdb_existing_database = 1;
553   } else {
554     if(flags & TRACKDB_OPEN_FOR_UPGRADE) {
555       /* Cannot upgrade a new database */
556       disorder_fatal(0, "cannot upgrade a database that does not exist");
557     }
558     /* This is a brand new database */
559     trackdb_existing_database = 0;
560   }
561   /* open the databases */
562   if(!(trackdb_usersdb = open_db("users.db",
563                                  0, DB_HASH, dbflags, 0600)))
564     disorder_fatal(0, "cannot open users.db");
565   trackdb_tracksdb = open_db("tracks.db",
566                              DB_RECNUM, DB_BTREE, dbflags, 0666);
567   trackdb_searchdb = open_db("search.db",
568                              DB_DUP|DB_DUPSORT, DB_HASH, dbflags, 0666);
569   trackdb_tagsdb = open_db("tags.db",
570                            DB_DUP|DB_DUPSORT, DB_HASH, dbflags, 0666);
571   trackdb_prefsdb = open_db("prefs.db", 0, DB_HASH, dbflags, 0666);
572   trackdb_globaldb = open_db("global.db", 0, DB_HASH, dbflags, 0666);
573   trackdb_noticeddb = open_db("noticed.db",
574                              DB_DUPSORT, DB_BTREE, dbflags, 0666);
575   trackdb_scheduledb = open_db("schedule.db", 0, DB_HASH, dbflags, 0666);
576   trackdb_playlistsdb = open_db("playlists.db", 0, DB_HASH, dbflags, 0666);
577   if(!trackdb_existing_database && !(flags & TRACKDB_READ_ONLY)) {
578     /* Stash the database version */
579     char buf[32];
580
581     assert(!(flags & TRACKDB_OPEN_FOR_UPGRADE));
582     snprintf(buf, sizeof buf, "%ld", config->dbversion);
583     trackdb_set_global("_dbversion", buf, 0);
584   }
585   D(("opened databases"));
586 }
587
588 /** @brief Close track databases */
589 void trackdb_close(void) {
590   int err;
591
592   /* sanity checks */
593   assert(opened == 1);
594   --opened;
595 #define CLOSE(N, V) do {                                                \
596   if(V && (err = V->close(V, 0)))                                       \
597     disorder_fatal(0, "error closing %s: %s", N, db_strerror(err));     \
598   V = 0;                                                                \
599 } while(0)
600   CLOSE("tracks.db", trackdb_tracksdb);
601   CLOSE("search.db", trackdb_searchdb);
602   CLOSE("tags.db", trackdb_tagsdb);
603   CLOSE("prefs.db", trackdb_prefsdb);
604   CLOSE("global.db", trackdb_globaldb);
605   CLOSE("noticed.db", trackdb_noticeddb);
606   CLOSE("schedule.db", trackdb_scheduledb);
607   CLOSE("users.db", trackdb_usersdb);
608   CLOSE("playlists.db", trackdb_playlistsdb);
609   D(("closed databases"));
610 }
611
612 /* generic db routines *******************************************************/
613
614 /** @brief Fetch and decode a database entry
615  * @param db Database
616  * @param track Track name
617  * @param kp Where to put decoded list (or NULL if you don't care)
618  * @param tid Owning transaction
619  * @return 0, @c DB_NOTFOUND or @c DB_LOCK_DEADLOCK
620  */
621 int trackdb_getdata(DB *db,
622                     const char *track,
623                     struct kvp **kp,
624                     DB_TXN *tid) {
625   int err;
626   DBT key, data;
627
628   switch(err = db->get(db, tid, make_key(&key, track),
629                        prepare_data(&data), 0)) {
630   case 0:
631     if(kp)
632       *kp = kvp_urldecode(data.data, data.size);
633     return 0;
634   case DB_NOTFOUND:
635     if(kp)
636       *kp = 0;
637     return err;
638   case DB_LOCK_DEADLOCK:
639     disorder_error(0, "error querying database: %s", db_strerror(err));
640     return err;
641   default:
642     disorder_fatal(0, "error querying database: %s", db_strerror(err));
643   }
644 }
645
646 /** @brief Encode and store a database entry
647  * @param db Database
648  * @param track Track name
649  * @param k List of key/value pairs to store
650  * @param tid Owning transaction
651  * @param flags DB flags e.g. DB_NOOVERWRITE
652  * @return 0, DB_KEYEXIST or DB_LOCK_DEADLOCK
653  */
654 int trackdb_putdata(DB *db,
655                     const char *track,
656                     const struct kvp *k,
657                     DB_TXN *tid,
658                     u_int32_t flags) {
659   int err;
660   DBT key, data;
661
662   switch(err = db->put(db, tid, make_key(&key, track),
663                        encode_data(&data, k), flags)) {
664   case 0:
665   case DB_KEYEXIST:
666     return err;
667   case DB_LOCK_DEADLOCK:
668     disorder_error(0, "error updating database: %s", db_strerror(err));
669     return err;
670   default:
671     disorder_fatal(0, "error updating database: %s", db_strerror(err));
672   }
673 }
674
675 /** @brief Delete a database entry
676  * @param db Database
677  * @param track Key to delete
678  * @param tid Transaction ID
679  * @return 0, DB_NOTFOUND or DB_LOCK_DEADLOCK
680  */
681 int trackdb_delkey(DB *db,
682                    const char *track,
683                    DB_TXN *tid) {
684   int err;
685
686   DBT key;
687   switch(err = db->del(db, tid, make_key(&key, track), 0)) {
688   case 0:
689   case DB_NOTFOUND:
690     return 0;
691   case DB_LOCK_DEADLOCK:
692     disorder_error(0, "error updating database: %s", db_strerror(err));
693     return err;
694   default:
695     disorder_fatal(0, "error updating database: %s", db_strerror(err));
696   }
697 }
698
699 /** @brief Open a database cursor
700  * @param db Database
701  * @param tid Owning transaction
702  * @return Cursor
703  */
704 DBC *trackdb_opencursor(DB *db, DB_TXN *tid) {
705   int err;
706   DBC *c;
707
708   switch(err = db->cursor(db, tid, &c, 0)) {
709   case 0: break;
710   default: disorder_fatal(0, "error creating cursor: %s", db_strerror(err));
711   }
712   return c;
713 }
714
715 /** @brief Close a database cursor
716  * @param c Cursor
717  * @return 0 or DB_LOCK_DEADLOCK
718  */
719 int trackdb_closecursor(DBC *c) {
720   int err;
721
722   if(!c) return 0;
723   switch(err = c->c_close(c)) {
724   case 0:
725     return err;
726   case DB_LOCK_DEADLOCK:
727     disorder_error(0, "error closing cursor: %s", db_strerror(err));
728     return err;
729   default:
730     disorder_fatal(0, "error closing cursor: %s", db_strerror(err));
731   }
732 }
733
734 /** @brief Delete a key/data pair
735  * @param db Database
736  * @param word Key
737  * @param track Data
738  * @param tid Owning transaction
739  * @return 0, DB_NOTFOUND or DB_LOCK_DEADLOCK
740  *
741  * Used by the search and tags databases, hence the odd parameter names.
742  * See also register_word().
743  */
744 int trackdb_delkeydata(DB *db,
745                        const char *word,
746                        const char *track,
747                        DB_TXN *tid) {
748   int err;
749   DBC *c;
750   DBT key, data;
751
752   c = trackdb_opencursor(db, tid);
753   switch(err = c->c_get(c, make_key(&key, word),
754                         make_key(&data, track), DB_GET_BOTH)) {
755   case 0:
756     switch(err = c->c_del(c, 0)) {
757     case 0:
758       break;
759     case DB_KEYEMPTY:
760       err = 0;
761       break;
762     case DB_LOCK_DEADLOCK:
763       disorder_error(0, "error updating database: %s", db_strerror(err));
764       break;
765     default:
766       disorder_fatal(0, "c->c_del: %s", db_strerror(err));
767     }
768     break;
769   case DB_NOTFOUND:
770     break;
771   case DB_LOCK_DEADLOCK:
772     disorder_error(0, "error updating database: %s", db_strerror(err));
773     break;
774   default:
775     disorder_fatal(0, "c->c_get: %s", db_strerror(err));
776   }
777   if(trackdb_closecursor(c)) err = DB_LOCK_DEADLOCK;
778   return err;
779 }
780
781 /** @brief Start a transaction
782  * @return Transaction
783  */
784 DB_TXN *trackdb_begin_transaction(void) {
785   DB_TXN *tid;
786   int err;
787
788   if((err = trackdb_env->txn_begin(trackdb_env, 0, &tid, 0)))
789     disorder_fatal(0, "trackdb_env->txn_begin: %s", db_strerror(err));
790   return tid;
791 }
792
793 /** @brief Abort transaction
794  * @param tid Transaction (or NULL)
795  *
796  * If @p tid is NULL then nothing happens.
797  */
798 void trackdb_abort_transaction(DB_TXN *tid) {
799   int err;
800
801   if(tid)
802     if((err = tid->abort(tid)))
803       disorder_fatal(0, "tid->abort: %s", db_strerror(err));
804 }
805
806 /** @brief Commit transaction
807  * @param tid Transaction (must not be NULL)
808  */
809 void trackdb_commit_transaction(DB_TXN *tid) {
810   int err;
811
812   if((err = tid->commit(tid, 0)))
813     disorder_fatal(0, "tid->commit: %s", db_strerror(err));
814 }
815
816 /* search/tags shared code ***************************************************/
817
818 /** @brief Comparison function used by dedupe()
819  * @param a Pointer to first key
820  * @param b Pointer to second key
821  * @return -1, 0 or 1
822  *
823  * Passed to qsort().
824  */
825 static int wordcmp(const void *a, const void *b) {
826   return strcmp(*(const char **)a, *(const char **)b);
827 }
828
829 /** @brief Sort and de-duplicate @p vec
830  * @param vec Vector to sort
831  * @param nvec Length of @p vec
832  * @return @p vec
833  *
834  * The returned vector is NULL-terminated, and there must be room for this NULL
835  * even if there are no duplicates (i.e. it must have more than @p nvec
836  * elements.)
837  */
838 static char **dedupe(char **vec, int nvec) {
839   int m, n;
840
841   qsort(vec, nvec, sizeof (char *), wordcmp);
842   m = n = 0;
843   if(nvec) {
844     vec[m++] = vec[0];
845     for(n = 1; n < nvec; ++n)
846       if(strcmp(vec[n], vec[m - 1]))
847         vec[m++] = vec[n];
848   }
849   vec[m] = 0;
850   return vec;
851 }
852
853 /** @brief Store a key/data pair
854  * @param db Database
855  * @param what Description
856  * @param track Data
857  * @param word Key
858  * @param tid Owning transaction
859  * @return 0 or DB_DEADLOCK
860  *
861  * Used by the search and tags databases, hence the odd parameter names.
862  * See also trackdb_delkeydata().
863  */
864 static int register_word(DB *db, const char *what,
865                          const char *track, const char *word,
866                          DB_TXN *tid) {
867   int err;
868   DBT key, data;
869
870   switch(err = db->put(db, tid, make_key(&key, word),
871                        make_key(&data, track), DB_NODUPDATA)) {
872   case 0:
873   case DB_KEYEXIST:
874     return 0;
875   case DB_LOCK_DEADLOCK:
876     disorder_error(0, "error updating %s.db: %s", what, db_strerror(err));
877     return err;
878   default:
879     disorder_fatal(0, "error updating %s.db: %s", what,  db_strerror(err));
880   }
881 }
882
883 /* search primitives *********************************************************/
884
885 /** @brief Return true iff @p name is a trackname_display_ pref
886  * @param name Preference name
887  * @return Non-zero iff @p name is a trackname_display_ pref
888  */
889 static int is_display_pref(const char *name) {
890   static const char prefix[] = "trackname_display_";
891   return !strncmp(name, prefix, (sizeof prefix) - 1);
892 }
893
894 /** @brief Word_Break property tailor that treats underscores as spaces
895  * @param c Code point
896  * @return Tailored property or -1 to use standard value
897  *
898  * Passed to utf32_word_split() when splitting a track name into words.
899  * See word_split() and @ref unicode_property_tailor.
900  */
901 static int tailor_underscore_Word_Break_Other(uint32_t c) {
902   switch(c) {
903   default:
904     return -1;
905   case 0x005F: /* LOW LINE (SPACING UNDERSCORE) */
906     return unicode_Word_Break_Other;
907   }
908 }
909
910 /** @brief Remove all combining characters in-place
911  * @param s Pointer to start of string
912  * @param ns Length of string
913  * @return New, possiblby reduced, length
914  */
915 static size_t remove_combining_chars(uint32_t *s, size_t ns) {
916   uint32_t *start = s, *t = s, *end = s + ns;
917
918   while(s < end) {
919     const uint32_t c = *s++;
920     if(!utf32_combining_class(c))
921       *t++ = c;
922   }
923   return t - start;
924 }
925
926 /** @brief Normalize and split a string using a given tailoring
927  * @param v Where to store words from string
928  * @param s Input string
929  * @param pt Word_Break property tailor, or NULL
930  *
931  * The output words will be:
932  * - case-folded
933  * - have any combination characters stripped
934  * - not include any word break code points (as tailored)
935  *
936  * Used by track_to_words(), with @p pt set to @ref
937  * tailor_underscore_Word_Break_Other, and by normalize_tag() with no
938  * tailoring.
939  */
940 static void word_split(struct vector *v,
941                        const char *s,
942                        unicode_property_tailor *pt) {
943   size_t nw, nt32, i;
944   uint32_t *t32, **w32;
945
946   /* Convert to UTF-32 */
947   if(!(t32 = utf8_to_utf32(s, strlen(s), &nt32)))
948     return;
949   /* Erase case distinctions */
950   if(!(t32 = utf32_casefold_compat(t32, nt32, &nt32)))
951     return;
952   /* Drop combining characters */
953   nt32 = remove_combining_chars(t32, nt32);
954   /* Split into words, treating _ as a space */
955   w32 = utf32_word_split(t32, nt32, &nw, pt);
956   /* Convert words back to UTF-8 and append to result */
957   for(i = 0; i < nw; ++i)
958     vector_append(v, utf32_to_utf8(w32[i], utf32_len(w32[i]), 0));
959 }
960
961 /** @brief Normalize a tag
962  * @param s Tag
963  * @param ns Length of tag
964  * @return Normalized string or NULL on error
965  *
966  * The return value will be:
967  * - case-folded
968  * - have no leading or trailing space
969  * - have no combining characters
970  * - all spacing between words will be a single U+0020 SPACE
971  */
972 static char *normalize_tag(const char *s, size_t ns) {
973   uint32_t *s32, **w32;
974   size_t ns32, nw32, i;
975   struct dynstr d[1];
976
977   if(!(s32 = utf8_to_utf32(s, ns, &ns32)))
978     return 0;
979   if(!(s32 = utf32_casefold_compat(s32, ns32, &ns32))) /* ->NFKD */
980     return 0;
981   ns32 = remove_combining_chars(s32, ns32);
982   /* Split into words, no Word_Break tailoring */
983   w32 = utf32_word_split(s32, ns32, &nw32, 0);
984   /* Compose back into a string */
985   dynstr_init(d);
986   for(i = 0; i < nw32; ++i) {
987     if(i)
988       dynstr_append(d, ' ');
989     dynstr_append_string(d, utf32_to_utf8(w32[i], utf32_len(w32[i]), 0));
990   }
991   dynstr_terminate(d);
992   return d->vec;
993 }
994
995 /** @brief Compute the words of a track name
996  * @param track Track name
997  * @param p Preferences (for display prefs)
998  * @return NULL-terminated, de-duplicated list or words
999  */
1000 static char **track_to_words(const char *track,
1001                              const struct kvp *p) {
1002   struct vector v;
1003   const char *rootless = track_rootless(track);
1004
1005   if(!rootless)
1006     rootless = track;                   /* bodge */
1007   vector_init(&v);
1008   rootless = strip_extension(rootless);
1009   word_split(&v, strip_extension(rootless), tailor_underscore_Word_Break_Other);
1010   for(; p; p = p->next)
1011     if(is_display_pref(p->name))
1012       word_split(&v, p->value, 0);
1013   vector_terminate(&v);
1014   return dedupe(v.vec, v.nvec);
1015 }
1016
1017 /** @brief Test for a stopword
1018  * @param word Word
1019  * @return Non-zero if @p word is a stopword
1020  */
1021 static int stopword(const char *word) {
1022   int n;
1023
1024   for(n = 0; n < config->stopword.n
1025         && strcmp(word, config->stopword.s[n]); ++n)
1026     ;
1027   return n < config->stopword.n;
1028 }
1029
1030 /** @brief Register a search term
1031  * @param track Track name
1032  * @param word A word that appears in the name of @p track
1033  * @param tid Owning transaction
1034  * @return  0 or DB_LOCK_DEADLOCK
1035  */
1036 static int register_search_word(const char *track, const char *word,
1037                                 DB_TXN *tid) {
1038   if(stopword(word)) return 0;
1039   return register_word(trackdb_searchdb, "search", track, word, tid);
1040 }
1041
1042 /* Tags **********************************************************************/
1043
1044 /** @brief Test for tag characters
1045  * @param c Character
1046  * @return Non-zero if @p c is a tag character
1047  *
1048  * The current rule is that commas and the control characters 0-31 are not
1049  * allowed but anything else is permitted.  This is arguably a bit loose.
1050  */
1051 static int tagchar(int c) {
1052   switch(c) {
1053   case ',':
1054     return 0;
1055   default:
1056     return c >= ' ';
1057   }
1058 }
1059
1060 /** @brief Parse a tag list
1061  * @param s Tag list or NULL (equivalent to "")
1062  * @return Parsed tag list
1063  *
1064  * The tags will be normalized (as per normalize_tag()) and de-duplicated.
1065  */
1066 char **parsetags(const char *s) {
1067   const char *t;
1068   struct vector v;
1069
1070   vector_init(&v);
1071   if(s) {
1072     /* skip initial separators */
1073     while(*s && (!tagchar(*s) || *s == ' '))
1074       ++s;
1075     while(*s) {
1076       /* find the extent of the tag */
1077       t = s;
1078       while(*s && tagchar(*s))
1079         ++s;
1080       /* strip trailing spaces */
1081       while(s > t && s[-1] == ' ')
1082         --s;
1083       /* add tag to list */
1084       vector_append(&v, normalize_tag(t, (size_t)(s - t)));
1085       /* skip intermediate and trailing separators */
1086       while(*s && (!tagchar(*s) || *s == ' '))
1087         ++s;
1088     }
1089   }
1090   vector_terminate(&v);
1091   return dedupe(v.vec, v.nvec);
1092 }
1093
1094 /** @brief Register a tag
1095  * @param track Track name
1096  * @param tag Tag name
1097  * @param tid Owning transaction
1098  * @return 0 or DB_LOCK_DEADLOCK
1099  */
1100 static int register_tag(const char *track, const char *tag, DB_TXN *tid) {
1101   return register_word(trackdb_tagsdb, "tags", track, tag, tid);
1102 }
1103
1104 /* aliases *******************************************************************/
1105
1106 /** @brief Compute an alias
1107  * @param aliasp Where to put alias (gets NULL if none)
1108  * @param track Track to find alias for
1109  * @param p Prefs for @p track
1110  * @param tid Owning transaction
1111  * @return 0 or DB_LOCK_DEADLOCK
1112  *
1113  * This function looks up the track name parts for @p track.  By default these
1114  * amount to the original values from the track name but are overridden by
1115  * preferences.
1116  *
1117  * These values are then substituted into the pattern defined by the @b alias
1118  * command; see disorder_config(5) for the syntax.
1119  *
1120  * The track is only considered to have an alias if all of the following are
1121  * true:
1122  * - a preference was used for at least one name part
1123  * - the result differs from the original track name
1124  * - the result does not match any existing track or alias
1125  */
1126 static int compute_alias(char **aliasp,
1127                          const char *track,
1128                          const struct kvp *p,
1129                          DB_TXN *tid) {
1130   struct dynstr d;
1131   const char *s = config->alias, *t, *expansion, *part;
1132   int c, used_db = 0, slash_prefix, err;
1133   struct kvp *at;
1134   const char *const root = find_track_root(track);
1135
1136   if(!root) {
1137     /* Bodge for tracks with no root */
1138     *aliasp = 0;
1139     return 0;
1140   }
1141   dynstr_init(&d);
1142   dynstr_append_string(&d, root);
1143   while((c = (unsigned char)*s++)) {
1144     if(c != '{') {
1145       dynstr_append(&d, c);
1146       continue;
1147     }
1148     if((slash_prefix = (*s == '/')))
1149       s++;
1150     t = strchr(s, '}');
1151     assert(t != 0);                     /* validated at startup */
1152     part = xstrndup(s, t - s);
1153     expansion = getpart(track, "display", part, p, &used_db);
1154     if(*expansion) {
1155       if(slash_prefix) dynstr_append(&d, '/');
1156       dynstr_append_string(&d, expansion);
1157     }
1158     s = t + 1;                          /* skip {part} */
1159   }
1160   /* only admit to the alias if we used the db... */
1161   if(!used_db) {
1162     *aliasp = 0;
1163     return 0;
1164   }
1165   dynstr_terminate(&d);
1166   /* ...and the answer differs from the original... */
1167   if(!strcmp(track, d.vec)) {
1168     *aliasp = 0;
1169     return 0;
1170   }
1171   /* ...and there isn't already a different track with that name (including as
1172    * an alias) */
1173   switch(err = trackdb_getdata(trackdb_tracksdb, d.vec, &at, tid)) {
1174   case 0:
1175     if((s = kvp_get(at, "_alias_for"))
1176        && !strcmp(s, track)) {
1177     case DB_NOTFOUND:
1178       *aliasp = d.vec;
1179     } else {
1180       *aliasp = 0;
1181     }
1182     return 0;
1183   default:
1184     return err;
1185   }
1186 }
1187
1188 /** @brief Assert that no alias is allowed for gettrackdata() */
1189 #define GTD_NOALIAS 0x0001
1190
1191 /** @brief Get all track data
1192  * @param track Track to look up; aliases allowed unless @ref GTD_NOALIAS
1193  * @param tp Where to put track data (if not NULL)
1194  * @param pp Where to put preferences (if not NULL)
1195  * @param actualp Where to put real (i.e. non-alias) path (if not NULL)
1196  * @param flags Flag values, see below
1197  * @param tid Owning transaction
1198  * @return 0, DB_NOTFOUND (track doesn't exist) or DB_LOCK_DEADLOCK
1199  *
1200  * Possible flags values are:
1201  * - @ref GTD_NOALIAS to assert that an alias is not allowed
1202  *
1203  * The return values are always set (even if to NULL).
1204  */
1205 static int gettrackdata(const char *track,
1206                         struct kvp **tp,
1207                         struct kvp **pp,
1208                         const char **actualp,
1209                         unsigned flags,
1210                         DB_TXN *tid) {
1211   int err;
1212   const char *actual = track;
1213   struct kvp *t = 0, *p = 0;
1214
1215   if((err = trackdb_getdata(trackdb_tracksdb, track, &t, tid))) goto done;
1216   if((actual = kvp_get(t, "_alias_for"))) {
1217     if(flags & GTD_NOALIAS) {
1218       disorder_error(0,
1219                      "alias passed to gettrackdata where real path required");
1220       abort();
1221     }
1222     if((err = trackdb_getdata(trackdb_tracksdb, actual, &t, tid))) goto done;
1223   } else
1224     actual = track;
1225   assert(actual != 0);
1226   if(pp) {
1227     if((err = trackdb_getdata(trackdb_prefsdb, actual, &p, tid)) == DB_LOCK_DEADLOCK)
1228       goto done;
1229   }
1230   err = 0;
1231 done:
1232   if(actualp) *actualp = actual;
1233   if(tp) *tp = t;
1234   if(pp) *pp = p;
1235   return err;
1236 }
1237
1238 /* trackdb_notice() **********************************************************/
1239
1240 /** @brief Notice a possibly new track
1241  * @param track NFC UTF-8 track name
1242  * @param path Raw path name (i.e. the bytes that came out of readdir())
1243  * @return @c DB_NOTFOUND if new, 0 if already known
1244  *
1245  * @c disorder-rescan is responsible for normalizing the track name.
1246  */
1247 int trackdb_notice(const char *track,
1248                    const char *path) {
1249   int err;
1250   DB_TXN *tid;
1251
1252   for(;;) {
1253     tid = trackdb_begin_transaction();
1254     err = trackdb_notice_tid(track, path, tid);
1255     if((err == DB_LOCK_DEADLOCK)) goto fail;
1256     break;
1257   fail:
1258     trackdb_abort_transaction(tid);
1259   }
1260   trackdb_commit_transaction(tid);
1261   return err;
1262 }
1263
1264 /** @brief Notice a possibly new track
1265  * @param track NFC UTF-8 track name
1266  * @param path Raw path name (i.e. the bytes that came out of readdir())
1267  * @param tid Owning transaction
1268  * @return @c DB_NOTFOUND if new, 0 if already known, @c DB_LOCK_DEADLOCK also
1269  *
1270  * @c disorder-rescan is responsible for normalizing the track name.
1271  */
1272 int trackdb_notice_tid(const char *track,
1273                        const char *path,
1274                        DB_TXN *tid) {
1275   int err, n;
1276   struct kvp *t, *a, *p;
1277   int t_changed, ret;
1278   char *alias, **w, *noticed;
1279   time_t now;
1280
1281   /* notice whether the tracks.db entry changes */
1282   t_changed = 0;
1283   /* get any existing tracks entry */
1284   if((err = gettrackdata(track, &t, &p, 0, 0, tid)) == DB_LOCK_DEADLOCK)
1285     return err;
1286   ret = err;                            /* 0 or DB_NOTFOUND */
1287   /* this is a real track */
1288   t_changed += kvp_set(&t, "_alias_for", 0);
1289   t_changed += kvp_set(&t, "_path", path);
1290   xtime(&now);
1291   if(ret == DB_NOTFOUND) {
1292     /* It's a new track; record the time */
1293     byte_xasprintf(&noticed, "%lld", (long long)now);
1294     t_changed += kvp_set(&t, "_noticed", noticed);
1295   }
1296   /* if we have an alias record it in the database */
1297   if((err = compute_alias(&alias, track, p, tid))) return err;
1298   if(alias) {
1299     /* won't overwrite someone else's alias as compute_alias() checks */
1300     D(("%s: alias %s", track, alias));
1301     a = 0;
1302     kvp_set(&a, "_alias_for", track);
1303     if((err = trackdb_putdata(trackdb_tracksdb, alias, a, tid, 0))) return err;
1304   }
1305   /* update search.db */
1306   w = track_to_words(track, p);
1307   for(n = 0; w[n]; ++n)
1308     if((err = register_search_word(track, w[n], tid)))
1309       return err;
1310   /* update tags.db */
1311   w = parsetags(kvp_get(p, "tags"));
1312   for(n = 0; w[n]; ++n)
1313     if((err = register_tag(track, w[n], tid)))
1314       return err;
1315   /* only store the tracks.db entry if it has changed */
1316   if(t_changed && (err = trackdb_putdata(trackdb_tracksdb, track, t, tid, 0)))
1317     return err;
1318   if(ret == DB_NOTFOUND) {
1319     uint32_t timestamp[2];
1320     DBT key, data;
1321
1322     timestamp[0] = htonl((uint64_t)now >> 32);
1323     timestamp[1] = htonl((uint32_t)now);
1324     memset(&key, 0, sizeof key);
1325     key.data = timestamp;
1326     key.size = sizeof timestamp;
1327     switch(err = trackdb_noticeddb->put(trackdb_noticeddb, tid, &key,
1328                                         make_key(&data, track), 0)) {
1329     case 0: break;
1330     case DB_LOCK_DEADLOCK: return err;
1331     default:
1332       disorder_fatal(0, "error updating noticed.db: %s", db_strerror(err));
1333     }
1334   }
1335   return ret;
1336 }
1337
1338 /* trackdb_obsolete() ********************************************************/
1339
1340 /** @brief Obsolete a track
1341  * @param track Track name
1342  * @param tid Owning transaction
1343  * @return 0 or DB_LOCK_DEADLOCK
1344  *
1345  * Discards a track from the database when it's known not to exist any more.
1346  * Returns 0 even if it wasn't recorded.
1347  */
1348 int trackdb_obsolete(const char *track, DB_TXN *tid) {
1349   int err, n;
1350   struct kvp *p;
1351   char *alias, **w;
1352
1353   if((err = gettrackdata(track, 0, &p, 0,
1354                          GTD_NOALIAS, tid)) == DB_LOCK_DEADLOCK)
1355     return err;
1356   else if(err == DB_NOTFOUND) return 0;
1357   /* compute the alias, if any, and delete it */
1358   if((err = compute_alias(&alias, track, p, tid))) return err;
1359   if(alias) {
1360     /* if the alias points to some other track then compute_alias won't
1361      * return it */
1362     if((err = trackdb_delkey(trackdb_tracksdb, alias, tid))
1363        && err != DB_NOTFOUND)
1364       return err;
1365   }
1366   /* update search.db */
1367   w = track_to_words(track, p);
1368   for(n = 0; w[n]; ++n)
1369     if(trackdb_delkeydata(trackdb_searchdb,
1370                           w[n], track, tid) == DB_LOCK_DEADLOCK)
1371       return err;
1372   /* update tags.db */
1373   w = parsetags(kvp_get(p, "tags"));
1374   for(n = 0; w[n]; ++n)
1375     if(trackdb_delkeydata(trackdb_tagsdb,
1376                           w[n], track, tid) == DB_LOCK_DEADLOCK)
1377       return err;
1378   /* update tracks.db */
1379   if(trackdb_delkey(trackdb_tracksdb, track, tid) == DB_LOCK_DEADLOCK)
1380     return err;
1381   /* We don't delete the prefs, so they survive temporary outages of the
1382    * (possibly virtual) track filesystem */
1383   return 0;
1384 }
1385
1386 /* trackdb_stats() ***********************************************************/
1387
1388 #define H(name) { #name, offsetof(DB_HASH_STAT, name) }
1389 #define B(name) { #name, offsetof(DB_BTREE_STAT, name) }
1390
1391 static const struct statinfo {
1392   const char *name;
1393   size_t offset;
1394 } statinfo_hash[] = {
1395   H(hash_magic),
1396   H(hash_version),
1397   H(hash_nkeys),
1398   H(hash_ndata),
1399   H(hash_pagesize),
1400   H(hash_ffactor),
1401   H(hash_buckets),
1402   H(hash_free),
1403   H(hash_bfree),
1404   H(hash_bigpages),
1405   H(hash_big_bfree),
1406   H(hash_overflows),
1407   H(hash_ovfl_free),
1408   H(hash_dup),
1409   H(hash_dup_free),
1410 }, statinfo_btree[] = {
1411   B(bt_magic),
1412   B(bt_version),
1413   B(bt_nkeys),
1414   B(bt_ndata),
1415   B(bt_pagesize),
1416   B(bt_minkey),
1417   B(bt_re_len),
1418   B(bt_re_pad),
1419   B(bt_levels),
1420   B(bt_int_pg),
1421   B(bt_leaf_pg),
1422   B(bt_dup_pg),
1423   B(bt_over_pg),
1424   B(bt_free),
1425   B(bt_int_pgfree),
1426   B(bt_leaf_pgfree),
1427   B(bt_dup_pgfree),
1428   B(bt_over_pgfree),
1429 };
1430
1431 /** @brief Look up DB statistics
1432  * @param v Where to store stats
1433  * @param database Database
1434  * @param si Pointer to table of stats
1435  * @param nsi Size of @p si
1436  * @param tid Owning transaction
1437  * @return 0 or DB_LOCK_DEADLOCK
1438  */
1439 static int get_stats(struct vector *v,
1440                      DB *database,
1441                      const struct statinfo *si,
1442                      size_t nsi,
1443                      DB_TXN *tid) {
1444   void *sp;
1445   size_t n;
1446   char *str;
1447   int err;
1448
1449   if(database) {
1450     switch(err = database->stat(database, tid, &sp, 0)) {
1451     case 0:
1452       break;
1453     case DB_LOCK_DEADLOCK:
1454       disorder_error(0, "error querying database: %s", db_strerror(err));
1455       return err;
1456     default:
1457       disorder_fatal(0, "error querying database: %s", db_strerror(err));
1458     }
1459     for(n = 0; n < nsi; ++n) {
1460       byte_xasprintf(&str, "%s=%"PRIuMAX, si[n].name,
1461                      (uintmax_t)*(u_int32_t *)((char *)sp + si[n].offset));
1462       vector_append(v, str);
1463     }
1464   }
1465   return 0;
1466 }
1467
1468 /** @brief One entry in the search league */
1469 struct search_entry {
1470   char *word;
1471   int n;
1472 };
1473
1474 /** @brief Add a word to the search league
1475  * @param se Pointer to search league
1476  * @param count Maximum size for search league
1477  * @param nse Current size of search league
1478  * @param word New word, or NULL
1479  * @param n How often @p word appears
1480  * @return New size of search league
1481  */
1482 static int register_search_entry(struct search_entry *se,
1483                                  int count,
1484                                  int nse,
1485                                  char *word,
1486                                  int n) {
1487   int i;
1488
1489   if(word && (nse < count || n > se[nse - 1].n)) {
1490     /* Find the starting point */
1491     if(nse == count)
1492       i = nse - 1;
1493     else
1494       i = nse++;
1495     /* Find the insertion point */
1496     while(i > 0 && n > se[i - 1].n)
1497       --i;
1498     memmove(&se[i + 1], &se[i], (nse - i - 1) * sizeof *se);
1499     se[i].word = word;
1500     se[i].n = n;
1501   }
1502   return nse;
1503 }
1504
1505 /** @brief Find the top @p count words in the search database
1506  * @param v Where to format the result
1507  * @param count Maximum number of words
1508  * @param tid Owning transaction
1509  * @return 0 or DB_LOCK_DEADLOCK
1510  */
1511 static int search_league(struct vector *v, int count, DB_TXN *tid) {
1512   struct search_entry *se;
1513   DBT k, d;
1514   DBC *cursor;
1515   int err, n = 0, nse = 0, i;
1516   char *word = 0;
1517   size_t wl = 0;
1518   char *str;
1519
1520   cursor = trackdb_opencursor(trackdb_searchdb, tid);
1521   se = xmalloc(count * sizeof *se);
1522   /* Walk across the whole database counting up the number of times each
1523    * word appears. */
1524   while(!(err = cursor->c_get(cursor, prepare_data(&k), prepare_data(&d),
1525                               DB_NEXT))) {
1526     if(word && wl == k.size && !strncmp(word, k.data, wl))
1527       ++n;                              /* same word again */
1528     else {
1529       nse = register_search_entry(se, count, nse, word, n);
1530       word = xstrndup(k.data, wl = k.size);
1531       n = 1;
1532     }
1533   }
1534   switch(err) {
1535   case DB_NOTFOUND:
1536     err = 0;
1537     break;
1538   case DB_LOCK_DEADLOCK:
1539     disorder_error(0, "error querying search database: %s", db_strerror(err));
1540     break;
1541   default:
1542     disorder_fatal(0, "error querying search database: %s", db_strerror(err));
1543   }
1544   if(trackdb_closecursor(cursor)) err = DB_LOCK_DEADLOCK;
1545   if(err) return err;
1546   nse = register_search_entry(se, count, nse, word, n);
1547   byte_xasprintf(&str, "Top %d search words:", nse);
1548   vector_append(v, str);
1549   for(i = 0; i < nse; ++i) {
1550     byte_xasprintf(&str, "%4d: %5d %s", i + 1, se[i].n, se[i].word);
1551     vector_append(v, str);
1552   }
1553   return 0;
1554 }
1555
1556 #define SI(what) statinfo_##what, \
1557                  sizeof statinfo_##what / sizeof (struct statinfo)
1558
1559 /** @brief Return a list of database stats
1560  * @param nstatsp Where to store number of lines (or NULL)
1561  * @return Database stats output
1562  *
1563  * This is called by @c disorder-stats.  Don't call it directly from elsewhere
1564  * as it can take unreasonably long.
1565  */
1566 char **trackdb_stats(int *nstatsp) {
1567   DB_TXN *tid;
1568   struct vector v;
1569
1570   vector_init(&v);
1571   for(;;) {
1572     tid = trackdb_begin_transaction();
1573     v.nvec = 0;
1574     vector_append(&v, (char *)"Tracks database stats:");
1575     if(get_stats(&v, trackdb_tracksdb, SI(btree), tid)) goto fail;
1576     vector_append(&v, (char *)"");
1577     vector_append(&v, (char *)"Search database stats:");
1578     if(get_stats(&v, trackdb_searchdb, SI(hash), tid)) goto fail;
1579     vector_append(&v, (char *)"");
1580     vector_append(&v, (char *)"Prefs database stats:");
1581     if(get_stats(&v, trackdb_prefsdb, SI(hash), tid)) goto fail;
1582     vector_append(&v, (char *)"");
1583     if(search_league(&v, 10, tid)) goto fail;
1584     vector_terminate(&v);
1585     break;
1586 fail:
1587     trackdb_abort_transaction(tid);
1588   }
1589   trackdb_commit_transaction(tid);
1590   if(nstatsp) *nstatsp = v.nvec;
1591   return v.vec;
1592 }
1593
1594 /** @brief State structure tracking @c disorder-stats */
1595 struct stats_details {
1596   void (*done)(char *data, void *u);
1597   void *u;
1598   int exited;                           /* subprocess exited */
1599   int closed;                           /* pipe close */
1600   int wstat;                            /* wait status from subprocess */
1601   struct dynstr data[1];                /* data read from pipe */
1602 };
1603
1604 /** @brief Called when @c disorder-stats may have completed
1605  * @param d Pointer to state structure
1606  *
1607  * Called from stats_finished() and stats_read().  Only proceeds when the
1608  * process has terminated and the output is complete.
1609  */
1610 static void stats_complete(struct stats_details *d) {
1611   char *s;
1612
1613   if(!(d->exited && d->closed))
1614     return;
1615   byte_xasprintf(&s, "\n"
1616                  "Server stats:\n"
1617                  "track lookup cache hits: %lu\n"
1618                  "track lookup cache misses: %lu\n",
1619                  cache_files_hits,
1620                  cache_files_misses);
1621   dynstr_append_string(d->data, s);
1622   dynstr_terminate(d->data);
1623   d->done(d->data->vec, d->u);
1624 }
1625
1626 /** @brief Called when @c disorder-stats exits
1627  * @param ev Event loop
1628  * @param pid Process ID
1629  * @param status Exit status
1630  * @param rusage Resource usage
1631  * @param u Pointer to state structure (@ref stats_details)
1632  * @return 0
1633  */
1634 static int stats_finished(ev_source attribute((unused)) *ev,
1635                           pid_t pid,
1636                           int status,
1637                           const struct rusage attribute((unused)) *rusage,
1638                           void *u) {
1639   struct stats_details *const d = u;
1640
1641   d->exited = 1;
1642   if(status)
1643     disorder_error(0, "disorder-stats %s", wstat(status));
1644   stats_complete(d);
1645   char *k;
1646   byte_xasprintf(&k, "%lu", (unsigned long)pid);
1647   hash_remove(stats_pids, k);
1648   return 0;
1649 }
1650
1651 /** @brief Called when pipe from @c disorder-stats is readable
1652  * @param ev Event loop
1653  * @param reader Reader state
1654  * @param ptr Pointer to bytes read
1655  * @param bytes Number of bytes available
1656  * @param eof Set at end of file
1657  * @param u Pointer to state structure (@ref stats_details)
1658  * @return 0
1659  */
1660 static int stats_read(ev_source attribute((unused)) *ev,
1661                       ev_reader *reader,
1662                       void *ptr,
1663                       size_t bytes,
1664                       int eof,
1665                       void *u) {
1666   struct stats_details *const d = u;
1667
1668   dynstr_append_bytes(d->data, ptr, bytes);
1669   ev_reader_consume(reader, bytes);
1670   if(eof)
1671     d->closed = 1;
1672   stats_complete(d);
1673   return 0;
1674 }
1675
1676 /** @brief Called when pipe from @c disorder-stats errors
1677  * @param ev Event loop
1678  * @param errno_value Error code
1679  * @param u Pointer to state structure (@ref stats_details)
1680  * @return 0
1681  */
1682 static int stats_error(ev_source attribute((unused)) *ev,
1683                        int errno_value,
1684                        void *u) {
1685   struct stats_details *const d = u;
1686
1687   disorder_error(errno_value, "error reading from pipe to disorder-stats");
1688   d->closed = 1;
1689   stats_complete(d);
1690   return 0;
1691 }
1692
1693 /** @brief Get database statistics via background process
1694  * @param ev Event loop
1695  * @param done Called on completion
1696  * @param u Passed to @p done
1697  *
1698  * Within the main server use this instead of trackdb_stats(), which can take
1699  * unreasonably long.
1700  */
1701 void trackdb_stats_subprocess(ev_source *ev,
1702                               void (*done)(char *data, void *u),
1703                               void *u) {
1704   int p[2];
1705   pid_t pid;
1706   struct stats_details *d = xmalloc(sizeof *d);
1707
1708   dynstr_init(d->data);
1709   d->done = done;
1710   d->u = u;
1711   xpipe(p);
1712   pid = subprogram(ev, p[1], "disorder-stats", (char *)0);
1713   xclose(p[1]);
1714   ev_child(ev, pid, 0, stats_finished, d);
1715   if(!ev_reader_new(ev, p[0], stats_read, stats_error, d,
1716                     "disorder-stats reader"))
1717     disorder_fatal(0, "ev_reader_new for disorder-stats reader failed");
1718   /* Remember the PID */
1719   if(!stats_pids)
1720     stats_pids = hash_new(1);
1721   char *k;
1722   byte_xasprintf(&k, "%lu", (unsigned long)pid);
1723   hash_add(stats_pids, k, "", HASH_INSERT);
1724 }
1725
1726 /** @brief Parse a track name part preference
1727  * @param name Preference name
1728  * @param partp Where to store part name
1729  * @param contextp Where to store context name
1730  * @return 0 on success, non-0 if parse fails
1731  */
1732 static int trackdb__parse_namepref(const char *name,
1733                                    char **partp,
1734                                    char **contextp) {
1735   char *c;
1736   static const char prefix[] = "trackname_";
1737   
1738   if(strncmp(name, prefix, strlen(prefix)))
1739     return -1;                          /* not trackname_* at all */
1740   name += strlen(prefix);
1741   /* There had better be a _ between context and part */
1742   c = strchr(name, '_');
1743   if(!c)
1744     return -1;
1745   /* Context is first in the pref name even though most APIs have the part
1746    * first.  Confusing; sorry. */
1747   *contextp = xstrndup(name, c - name);
1748   ++c;
1749   /* There had better NOT be a second _ */
1750   if(strchr(c, '_'))
1751     return -1;
1752   *partp = xstrdup(c);
1753   return 0;
1754 }
1755
1756 /** @brief Compute the default value for a track preference
1757  * @param track Track name
1758  * @param name Preference name
1759  * @return Default value or 0 if none/not known
1760  */
1761 static const char *trackdb__default(const char *track, const char *name) {
1762   char *context, *part;
1763   
1764   if(!trackdb__parse_namepref(name, &part, &context)) {
1765     /* We can work out the default for a trackname_ pref */
1766     return trackname_part(track, context, part);
1767   } else if(!strcmp(name, "weight")) {
1768     /* We know the default weight */
1769     return "90000";
1770   } else if(!strcmp(name, "pick_at_random")) {
1771     /* By default everything is eligible for picking at random */
1772     return "1";
1773   } else if(!strcmp(name, "tags")) {
1774     /* By default everything no track has any tags */
1775     return "";
1776   }
1777   return 0;
1778 }
1779
1780 /** @brief Set a preference
1781  * @param track Track to modify
1782  * @param name Preference name
1783  * @param value New value, or NULL to erase any existing value
1784  * @return 0 on success or non-zero if not allowed to set preference
1785  */
1786 int trackdb_set(const char *track,
1787                 const char *name,
1788                 const char *value) {
1789   struct kvp *t, *p, *a;
1790   DB_TXN *tid;
1791   int err, cmp;
1792   char *oldalias, *newalias, **oldtags = 0, **newtags;
1793   const char *def;
1794
1795   /* If the value matches the default then unset instead, to keep the database
1796    * tidy.  Older versions did not have this feature so your database may yet
1797    * have some default values stored in it. */
1798   if(value) {
1799     def = trackdb__default(track, name);
1800     if(def && !strcmp(value, def))
1801       value = 0;
1802   }
1803
1804   for(;;) {
1805     tid = trackdb_begin_transaction();
1806     if((err = gettrackdata(track, &t, &p, 0,
1807                            0, tid)) == DB_LOCK_DEADLOCK)
1808       goto fail;
1809     if(err == DB_NOTFOUND) break;
1810     if(name[0] == '_') {
1811       if(kvp_set(&t, name, value))
1812         if(trackdb_putdata(trackdb_tracksdb, track, t, tid, 0))
1813           goto fail;
1814     } else {
1815       /* get the old alias name */
1816       if(compute_alias(&oldalias, track, p, tid)) goto fail;
1817       /* get the old tags */
1818       if(!strcmp(name, "tags"))
1819         oldtags = parsetags(kvp_get(p, "tags"));
1820       /* set the value */
1821       if(kvp_set(&p, name, value))
1822         if(trackdb_putdata(trackdb_prefsdb, track, p, tid, 0))
1823           goto fail;
1824       /* compute the new alias name */
1825       if((err = compute_alias(&newalias, track, p, tid))) goto fail;
1826       /* check whether alias has changed */
1827       if(!(oldalias == newalias
1828            || (oldalias && newalias && !strcmp(oldalias, newalias)))) {
1829         /* adjust alias records to fit change */
1830         if(oldalias
1831            && trackdb_delkey(trackdb_tracksdb, oldalias, tid) == DB_LOCK_DEADLOCK)
1832           goto fail;
1833         if(newalias) {
1834           a = 0;
1835           kvp_set(&a, "_alias_for", track);
1836           if(trackdb_putdata(trackdb_tracksdb, newalias, a, tid, 0)) goto fail;
1837         }
1838       }
1839       /* check whether tags have changed */
1840       if(!strcmp(name, "tags")) {
1841         newtags = parsetags(value);
1842         while(*oldtags || *newtags) {
1843           if(*oldtags && *newtags) {
1844             cmp = strcmp(*oldtags, *newtags);
1845             if(!cmp) {
1846               /* keeping this tag */
1847               ++oldtags;
1848               ++newtags;
1849             } else if(cmp < 0)
1850               /* old tag fits into a gap in the new list, so delete old */
1851               goto delete_old;
1852             else
1853               /* new tag fits into a gap in the old list, so insert new */
1854               goto insert_new;
1855           } else if(*oldtags) {
1856             /* we've run out of new tags, so remaining old ones are to be
1857              * deleted */
1858           delete_old:
1859             if(trackdb_delkeydata(trackdb_tagsdb,
1860                                   *oldtags, track, tid) == DB_LOCK_DEADLOCK)
1861               goto fail;
1862             ++oldtags;
1863           } else {
1864             /* we've run out of old tags, so remainig new ones are to be
1865              * inserted */
1866           insert_new:
1867             if(register_tag(track, *newtags, tid)) goto fail;
1868             ++newtags;
1869           }
1870         }
1871       }
1872     }
1873     err = 0;
1874     break;
1875 fail:
1876     trackdb_abort_transaction(tid);
1877   }
1878   trackdb_commit_transaction(tid);
1879   return err == 0 ? 0 : -1;
1880 }
1881
1882 /** @brief Get the value of a preference
1883  * @param track Track name
1884  * @param name Preference name
1885  * @return Preference value or NULL if it's not set
1886  */
1887 const char *trackdb_get(const char *track,
1888                         const char *name) {
1889   return kvp_get(trackdb_get_all(track), name);
1890 }
1891
1892 /** @brief Get all preferences for a track
1893  * @param track Track name
1894  * @return Linked list of preferences
1895  */
1896 struct kvp *trackdb_get_all(const char *track) {
1897   struct kvp *t, *p, **pp;
1898   DB_TXN *tid;
1899
1900   for(;;) {
1901     tid = trackdb_begin_transaction();
1902     if(gettrackdata(track, &t, &p, 0, 0, tid) == DB_LOCK_DEADLOCK)
1903       goto fail;
1904     break;
1905 fail:
1906     trackdb_abort_transaction(tid);
1907   }
1908   trackdb_commit_transaction(tid);
1909   for(pp = &p; *pp; pp = &(*pp)->next)
1910     ;
1911   *pp = t;
1912   return p;
1913 }
1914
1915 /** @brief Resolve an alias
1916  * @param track Track name (might be an alias)
1917  * @return Real track name (definitely not an alias) or NULL if no such track
1918  */
1919 const char *trackdb_resolve(const char *track) {
1920   DB_TXN *tid;
1921   const char *actual;
1922
1923   for(;;) {
1924     tid = trackdb_begin_transaction();
1925     if(gettrackdata(track, 0, 0, &actual, 0, tid) == DB_LOCK_DEADLOCK)
1926       goto fail;
1927     break;
1928 fail:
1929     trackdb_abort_transaction(tid);
1930   }
1931   trackdb_commit_transaction(tid);
1932   return actual;
1933 }
1934
1935 /** @brief Detect an alias
1936  * @param track Track name
1937  * @return Nonzero if @p track exists and is an alias
1938  */
1939 int trackdb_isalias(const char *track) {
1940   const char *actual = trackdb_resolve(track);
1941
1942   return strcmp(actual, track);
1943 }
1944
1945 /** @brief Detect whether a track exists
1946  * @param track Track name (can be an alias)
1947  * @return Nonzero if @p track exists (whether or not it's an alias)
1948  */
1949 int trackdb_exists(const char *track) {
1950   DB_TXN *tid;
1951   int err;
1952
1953   for(;;) {
1954     tid = trackdb_begin_transaction();
1955     /* unusually, here we want the return value */
1956     if((err = gettrackdata(track, 0, 0, 0, 0, tid)) == DB_LOCK_DEADLOCK)
1957       goto fail;
1958     break;
1959 fail:
1960     trackdb_abort_transaction(tid);
1961   }
1962   trackdb_commit_transaction(tid);
1963   return (err == 0);
1964 }
1965
1966 /** @brief Return list of all known tags
1967  * @return NULL-terminated tag list
1968  */
1969 char **trackdb_alltags(void) {
1970   int e;
1971   struct vector v[1];
1972
1973   vector_init(v);
1974   WITH_TRANSACTION(trackdb_listkeys(trackdb_tagsdb, v, tid));
1975   return v->vec;
1976 }
1977
1978 /** @brief List all the keys in @p db
1979  * @param db Database
1980  * @param v Vector to store keys in
1981  * @param tid Transaction ID
1982  * @return 0 or DB_LOCK_DEADLOCK
1983  */
1984 int trackdb_listkeys(DB *db, struct vector *v, DB_TXN *tid) {
1985   int e;
1986   DBT k, d;
1987   DBC *const c = trackdb_opencursor(db, tid);
1988
1989   v->nvec = 0;
1990   memset(&k, 0, sizeof k);
1991   while(!(e = c->c_get(c, &k, prepare_data(&d), DB_NEXT_NODUP)))
1992     vector_append(v, xstrndup(k.data, k.size));
1993   switch(e) {
1994   case DB_NOTFOUND:
1995     break;
1996   case DB_LOCK_DEADLOCK:
1997     return e;
1998   default:
1999     disorder_fatal(0, "c->c_get: %s", db_strerror(e));
2000   }
2001   if((e = trackdb_closecursor(c)))
2002     return e;
2003   vector_terminate(v);
2004   return 0;
2005 }
2006
2007 /* return 1 iff sorted tag lists A and B have at least one member in common */
2008 /** @brief Detect intersecting tag lists
2009  * @param a First list of tags (NULL-terminated)
2010  * @param b Second list of tags (NULL-terminated)
2011  * @return 1 if @p a and @p b have at least one member in common
2012  *
2013  * @p a and @p must be sorted.
2014  */
2015 int tag_intersection(char **a, char **b) {
2016   int cmp;
2017
2018   /* Same sort of logic as trackdb_set() above */
2019   while(*a && *b) {
2020     if(!(cmp = strcmp(*a, *b))) return 1;
2021     else if(cmp < 0) ++a;
2022     else ++b;
2023   }
2024   return 0;
2025 }
2026
2027 /** @brief Called when disorder-choose might have completed
2028  * @param ev Event loop
2029  * @param which @ref CHOOSE_RUNNING or @ref CHOOSE_READING
2030  *
2031  * Once called with both @p which values, @ref choose_callback is called
2032  * (usually chosen_random_track()).
2033  */
2034 static void choose_finished(ev_source *ev, unsigned which) {
2035   choose_complete |= which;
2036   if(choose_complete != (CHOOSE_RUNNING|CHOOSE_READING))
2037     return;
2038   choose_pid = -1;
2039   if(choose_status == 0 && choose_output.nvec > 0) {
2040     dynstr_terminate(&choose_output);
2041     choose_callback(ev, xstrdup(choose_output.vec));
2042   } else
2043     choose_callback(ev, 0);
2044 }
2045
2046 /** @brief Called when @c disorder-choose terminates
2047  * @param ev Event loop
2048  * @param pid Process ID
2049  * @param status Exit status
2050  * @param rusage Resource usage
2051  * @param u User data
2052  * @return 0
2053  */
2054 static int choose_exited(ev_source *ev,
2055                          pid_t attribute((unused)) pid,
2056                          int status,
2057                          const struct rusage attribute((unused)) *rusage,
2058                          void attribute((unused)) *u) {
2059   if(status)
2060     disorder_error(0, "disorder-choose %s", wstat(status));
2061   choose_status = status;
2062   choose_finished(ev, CHOOSE_RUNNING);
2063   return 0;
2064 }
2065
2066 /** @brief Called with data from @c disorder-choose pipe
2067  * @param ev Event loop
2068  * @param reader Reader state
2069  * @param ptr Data read
2070  * @param bytes Number of bytes read
2071  * @param eof Set at end of file
2072  * @param u User data
2073  * @return 0
2074  */
2075 static int choose_readable(ev_source *ev,
2076                            ev_reader *reader,
2077                            void *ptr,
2078                            size_t bytes,
2079                            int eof,
2080                            void attribute((unused)) *u) {
2081   dynstr_append_bytes(&choose_output, ptr, bytes);
2082   ev_reader_consume(reader, bytes);
2083   if(eof)
2084     choose_finished(ev, CHOOSE_READING);
2085   return 0;
2086 }
2087
2088 /** @brief Called when @c disorder-choose pipe errors
2089  * @param ev Event loop
2090  * @param errno_value Error code
2091  * @param u User data
2092  * @return 0
2093  */
2094 static int choose_read_error(ev_source *ev,
2095                              int errno_value,
2096                              void attribute((unused)) *u) {
2097   disorder_error(errno_value, "error reading disorder-choose pipe");
2098   choose_finished(ev, CHOOSE_READING);
2099   return 0;
2100 }
2101
2102 /** @brief Request a random track
2103  * @param ev Event source
2104  * @param callback Called with random track or NULL
2105  * @return 0 if a request was initiated, else -1
2106  *
2107  * Initiates a random track choice.  @p callback will later be called back with
2108  * the choice (or NULL on error).  If a choice is already underway then -1 is
2109  * returned and there will be no additional callback.
2110  *
2111  * The caller shouldn't assume that the track returned actually exists (it
2112  * might be removed between the choice and the callback, or between being added
2113  * to the queue and being played).
2114  */
2115 int trackdb_request_random(ev_source *ev,
2116                            random_callback *callback) {
2117   int p[2];
2118   
2119   if(choose_pid != -1)
2120     return -1;                          /* don't run concurrent chooses */
2121   xpipe(p);
2122   cloexec(p[0]);
2123   choose_pid = subprogram(ev, p[1], "disorder-choose", (char *)0);
2124   choose_fd = p[0];
2125   xclose(p[1]);
2126   choose_callback = callback;
2127   choose_output.nvec = 0;
2128   choose_complete = 0;
2129   if(!ev_reader_new(ev, p[0], choose_readable, choose_read_error, 0,
2130                     "disorder-choose reader")) /* owns p[0] */
2131     disorder_fatal(0, "ev_reader_new for disorder-choose reader failed");
2132   ev_child(ev, choose_pid, 0, choose_exited, 0); /* owns the subprocess */
2133   return 0;
2134 }
2135
2136 /** @brief Get a track name part, using prefs
2137  * @param track Track name
2138  * @param context Context ("display" etc)
2139  * @param part Part ("album" etc)
2140  * @param p Preference
2141  * @param used_db Set if a preference is used
2142  * @return Name part (never NULL)
2143  *
2144  * Used by compute_alias() and trackdb_getpart().
2145  */
2146 static const char *getpart(const char *track,
2147                            const char *context,
2148                            const char *part,
2149                            const struct kvp *p,
2150                            int *used_db) {
2151   const char *result;
2152   char *pref;
2153
2154   byte_xasprintf(&pref, "trackname_%s_%s", context, part);
2155   if((result = kvp_get(p, pref)))
2156     *used_db = 1;
2157   else
2158     result = trackname_part(track, context, part);
2159   assert(result != 0);
2160   return result;
2161 }
2162
2163 /** @brief Get a track name part
2164  * @param track Track name
2165  * @param context Context ("display" etc)
2166  * @param part Part ("album" etc)
2167  * @return Name part (never NULL)
2168  *
2169  * This is interface used by c_part().
2170  */
2171 const char *trackdb_getpart(const char *track,
2172                             const char *context,
2173                             const char *part) {
2174   struct kvp *p;
2175   DB_TXN *tid;
2176   char *pref;
2177   const char *actual;
2178   int used_db, err;
2179
2180   /* construct the full pref */
2181   byte_xasprintf(&pref, "trackname_%s_%s", context, part);
2182   for(;;) {
2183     tid = trackdb_begin_transaction();
2184     if((err = gettrackdata(track, 0, &p, &actual, 0, tid)) == DB_LOCK_DEADLOCK)
2185       goto fail;
2186     break;
2187 fail:
2188     trackdb_abort_transaction(tid);
2189   }
2190   trackdb_commit_transaction(tid);
2191   return getpart(actual, context, part, p, &used_db);
2192 }
2193
2194 /** @brief Get the raw (filesystem) path for @p track
2195  * @param track track Track name (can be an alias)
2196  * @return Raw path (never NULL)
2197  *
2198  * The raw path is the actual bytes that came out of readdir() etc.
2199  */
2200 const char *trackdb_rawpath(const char *track) {
2201   DB_TXN *tid;
2202   struct kvp *t;
2203   const char *path;
2204
2205   for(;;) {
2206     tid = trackdb_begin_transaction();
2207     if(gettrackdata(track, &t, 0, 0, 0, tid) == DB_LOCK_DEADLOCK)
2208       goto fail;
2209     break;
2210 fail:
2211     trackdb_abort_transaction(tid);
2212   }
2213   trackdb_commit_transaction(tid);
2214   if(!(path = kvp_get(t, "_path"))) path = track;
2215   return path;
2216 }
2217
2218 /* trackdb_list **************************************************************/
2219
2220 /* this is incredibly ugly, sorry, perhaps it will be rewritten to be actually
2221  * readable at some point */
2222
2223 /* return true if the basename of TRACK[0..TL-1], as defined by DL, matches RE.
2224  * If RE is a null pointer then it matches everything. */
2225 /** @brief Match a track against a rgeexp
2226  * @param dl Length of directory part of track
2227  * @param track Track name
2228  * @param tl Length of track name
2229  * @param re Regular expression or NULL
2230  * @return Nonzero on match
2231  *
2232  * @p tl is the total length of @p track, @p dl is the length of the directory
2233  * part (the index of the final "/").  The subject of the regexp match is the
2234  * basename, i.e. the part after @p dl.
2235  *
2236  * If @p re is NULL then always matches.
2237  */
2238 static int track_matches(size_t dl, const char *track, size_t tl,
2239                          const pcre *re) {
2240   int ovec[3], rc;
2241
2242   if(!re)
2243     return 1;
2244   track += dl + 1;
2245   tl -= (dl + 1);
2246   switch(rc = pcre_exec(re, 0, track, tl, 0, 0, ovec, 3)) {
2247   case PCRE_ERROR_NOMATCH: return 0;
2248   default:
2249     if(rc < 0) {
2250       disorder_error(0, "pcre_exec returned %d, subject '%s'", rc, track);
2251       return 0;
2252     }
2253     return 1;
2254   }
2255 }
2256
2257 /** @brief Generate a list of tracks and/or directories in @p dir
2258  * @param v Where to put results
2259  * @param dir Directory to list
2260  * @param what Bitmap of objects to return
2261  * @param re Regexp to filter matches (or NULL to accept all)
2262  * @param tid Owning transaction
2263  * @return 0 or DB_LOCK_DEADLOCK
2264  */
2265 static int do_list(struct vector *v, const char *dir,
2266                    enum trackdb_listable what, const pcre *re, DB_TXN *tid) {
2267   DBC *cursor;
2268   DBT k, d;
2269   size_t dl;
2270   char *ptr;
2271   int err;
2272   size_t l, last_dir_len = 0;
2273   char *last_dir = 0, *track;
2274   struct kvp *p;
2275
2276   dl = strlen(dir);
2277   cursor = trackdb_opencursor(trackdb_tracksdb, tid);
2278   make_key(&k, dir);
2279   prepare_data(&d);
2280   /* find the first key >= dir */
2281   err = cursor->c_get(cursor, &k, &d, DB_SET_RANGE);
2282   /* keep going while we're dealing with <dir/anything> */
2283   while(err == 0
2284         && k.size > dl
2285         && ((char *)k.data)[dl] == '/'
2286         && !memcmp(k.data, dir, dl)) {
2287     ptr = memchr((char *)k.data + dl + 1, '/', k.size - (dl + 1));
2288     if(ptr) {
2289       /* we have <dir/component/anything>, so <dir/component> is a directory */
2290       l = ptr - (char *)k.data;
2291       if(what & trackdb_directories)
2292         if(!(last_dir
2293              && l == last_dir_len
2294              && !memcmp(last_dir, k.data, l))) {
2295           last_dir = xstrndup(k.data, last_dir_len = l);
2296           if(track_matches(dl, k.data, l, re))
2297             vector_append(v, last_dir);
2298         }
2299     } else {
2300       /* found a plain file */
2301       if((what & trackdb_files)) {
2302         track = xstrndup(k.data, k.size);
2303         if((err = trackdb_getdata(trackdb_prefsdb,
2304                                   track, &p, tid)) == DB_LOCK_DEADLOCK)
2305           goto deadlocked;
2306         /* There's an awkward question here...
2307          *
2308          * If a track shares a directory with its alias then we could
2309          * do one of three things:
2310          * - report both.  Looks ridiculuous in most UIs.
2311          * - report just the alias.  Remarkably inconvenient to write
2312          *   UI code for!
2313          * - report just the real name.  Ugly if the UI doesn't prettify
2314          *   names via the name parts.
2315          */
2316 #if 1
2317         /* If this file is an alias for a track in the same directory then we
2318          * skip it */
2319         struct kvp *t = kvp_urldecode(d.data, d.size);
2320         const char *alias_target = kvp_get(t, "_alias_for");
2321         if(!(alias_target
2322              && !strcmp(d_dirname(alias_target),
2323                         d_dirname(track))))
2324           if(track_matches(dl, k.data, k.size, re))
2325             vector_append(v, track);
2326 #else
2327         /* if this file has an alias in the same directory then we skip it */
2328            char *alias;
2329         if((err = compute_alias(&alias, track, p, tid)))
2330           goto deadlocked;
2331         if(!(alias && !strcmp(d_dirname(alias), d_dirname(track))))
2332           if(track_matches(dl, k.data, k.size, re))
2333             vector_append(v, track);
2334 #endif
2335       }
2336     }
2337     err = cursor->c_get(cursor, &k, &d, DB_NEXT);
2338   }
2339   switch(err) {
2340   case 0:
2341     break;
2342   case DB_NOTFOUND:
2343     err = 0;
2344     break;
2345   case DB_LOCK_DEADLOCK:
2346     disorder_error(0, "error querying database: %s", db_strerror(err));
2347     break;
2348   default:
2349     disorder_fatal(0, "error querying database: %s", db_strerror(err));
2350   }
2351 deadlocked:
2352   if(trackdb_closecursor(cursor)) err = DB_LOCK_DEADLOCK;
2353   return err;
2354 }
2355
2356 /** @brief Get the directories or files below @p dir
2357  * @param dir Directory to list
2358  * @param np Where to put number of results (or NULL)
2359  * @param what Bitmap of objects to return
2360  * @param re Regexp to filter matches (or NULL to accept all)
2361  * @return List of tracks
2362  */
2363 char **trackdb_list(const char *dir, int *np, enum trackdb_listable what,
2364                     const pcre *re) {
2365   DB_TXN *tid;
2366   int n;
2367   struct vector v;
2368
2369   vector_init(&v);
2370   for(;;) {
2371     tid = trackdb_begin_transaction();
2372     v.nvec = 0;
2373     if(dir) {
2374       if(do_list(&v, dir, what, re, tid))
2375         goto fail;
2376     } else {
2377       for(n = 0; n < config->collection.n; ++n)
2378         if(do_list(&v, config->collection.s[n].root, what, re, tid))
2379           goto fail;
2380     }
2381     break;
2382 fail:
2383     trackdb_abort_transaction(tid);
2384   }
2385   trackdb_commit_transaction(tid);
2386   vector_terminate(&v);
2387   if(np)
2388     *np = v.nvec;
2389   return v.vec;
2390 }
2391
2392 /** @brief Detect a tag element in a search string
2393  * @param s Element of search string
2394  * @return Pointer to tag name (in @p s) if this is a tag: search, else NULL
2395  *
2396  * Tag searches take the form "tag:TAG".
2397  */
2398 static const char *checktag(const char *s) {
2399   if(!strncmp(s, "tag:", 4))
2400     return s + 4;
2401   else
2402     return 0;
2403 }
2404
2405 /* return a list of tracks containing all of the words given.  If you
2406  * ask for only stopwords you get no tracks. */
2407 char **trackdb_search(char **wordlist, int nwordlist, int *ntracks) {
2408   const char **w, *best = 0, *tag;
2409   char **twords, **tags;
2410   char *istag;
2411   int i, j, n, err, what;
2412   DBC *cursor = 0;
2413   DBT k, d;
2414   struct vector u, v;
2415   DB_TXN *tid;
2416   struct kvp *p;
2417   int ntags = 0;
2418   DB *db;
2419   const char *dbname;
2420
2421   *ntracks = 0;                         /* for early returns */
2422   /* normalize all the words */
2423   w = xmalloc(nwordlist * sizeof (char *));
2424   istag = xmalloc_noptr(nwordlist);
2425   for(n = 0; n < nwordlist; ++n) {
2426     uint32_t *w32;
2427     size_t nw32;
2428
2429     w[n] = utf8_casefold_compat(wordlist[n], strlen(wordlist[n]), 0);
2430     if(checktag(w[n])) {
2431       ++ntags;         /* count up tags */
2432       /* Normalize the tag */
2433       w[n] = normalize_tag(w[n] + 4, strlen(w[n] + 4));
2434       istag[n] = 1;
2435     } else {
2436       /* Normalize the search term by removing combining characters */
2437       if(!(w32 = utf8_to_utf32(w[n], strlen(w[n]), &nw32)))
2438         return 0;
2439       nw32 = remove_combining_chars(w32, nw32);
2440       if(!(w[n] = utf32_to_utf8(w32, nw32, 0)))
2441         return 0;
2442       istag[n] = 0;
2443     }
2444   }
2445   /* find the longest non-stopword */
2446   for(n = 0; n < nwordlist; ++n)
2447     if(!istag[n] && !stopword(w[n]))
2448       if(!best || strlen(w[n]) > strlen(best))
2449         best = w[n];
2450   /* TODO: we should at least in principal be able to identify the word or tag
2451    * with the least matches in log time, and choose that as our primary search
2452    * term. */
2453   if(ntags && !best) {
2454     /* Only tags are listed.  We limit to the first and narrow down with the
2455      * rest. */
2456     best = istag[0] ? w[0] : 0;
2457     db = trackdb_tagsdb;
2458     dbname = "tags";
2459   } else if(best) {
2460     /* We can limit to some word. */
2461     db = trackdb_searchdb;
2462     dbname = "search";
2463   } else {
2464     /* Only stopwords */
2465     return 0;
2466   }
2467   vector_init(&u);
2468   vector_init(&v);
2469   for(;;) {
2470     tid = trackdb_begin_transaction();
2471     /* find all the tracks that have that word */
2472     make_key(&k, best);
2473     prepare_data(&d);
2474     what = DB_SET;
2475     v.nvec = 0;
2476     cursor = trackdb_opencursor(db, tid);
2477     while(!(err = cursor->c_get(cursor, &k, &d, what))) {
2478       vector_append(&v, xstrndup(d.data, d.size));
2479       what = DB_NEXT_DUP;
2480     }
2481     switch(err) {
2482     case DB_NOTFOUND:
2483       err = 0;
2484       break;
2485     case DB_LOCK_DEADLOCK:
2486       disorder_error(0, "error querying %s database: %s",
2487                      dbname, db_strerror(err));
2488       break;
2489     default:
2490       disorder_fatal(0, "error querying %s database: %s",
2491                      dbname, db_strerror(err));
2492     }
2493     if(trackdb_closecursor(cursor)) err = DB_LOCK_DEADLOCK;
2494     cursor = 0;
2495     /* do a naive search over that (hopefuly fairly small) list of tracks */
2496     u.nvec = 0;
2497     for(n = 0; n < v.nvec; ++n) {
2498       if((err = gettrackdata(v.vec[n], 0, &p, 0, 0, tid) == DB_LOCK_DEADLOCK))
2499         goto fail;
2500       else if(err) {
2501         disorder_error(0, "track %s unexpected error: %s",
2502                        v.vec[n], db_strerror(err));
2503         continue;
2504       }
2505       twords = track_to_words(v.vec[n], p);
2506       tags = parsetags(kvp_get(p, "tags"));
2507       for(i = 0; i < nwordlist; ++i) {
2508         if(istag[i]) {
2509           tag = w[i];
2510           /* Track must have this tag */
2511           for(j = 0; tags[j]; ++j)
2512             if(!strcmp(tag, tags[j])) break; /* tag found */
2513           if(!tags[j]) break;           /* tag not found */
2514         } else {
2515           /* Track must contain this word */
2516           for(j = 0; twords[j]; ++j)
2517             if(!strcmp(w[i], twords[j])) break; /* word found */
2518           if(!twords[j]) break;         /* word not found */
2519         }
2520       }
2521       if(i >= nwordlist)                /* all words found */
2522         vector_append(&u, v.vec[n]);
2523     }
2524     break;
2525   fail:
2526     trackdb_closecursor(cursor);
2527     cursor = 0;
2528     trackdb_abort_transaction(tid);
2529     disorder_info("retrying search");
2530   }
2531   trackdb_commit_transaction(tid);
2532   vector_terminate(&u);
2533   if(ntracks)
2534     *ntracks = u.nvec;
2535   return u.vec;
2536 }
2537
2538 /* trackdb_scan **************************************************************/
2539
2540 /** @brief Visit every track
2541  * @param root Root to scan or NULL for all
2542  * @param callback Callback for each track
2543  * @param u Passed to @p callback
2544  * @param tid Owning transaction
2545  * @return 0, DB_LOCK_DEADLOCK or EINTR
2546  *
2547  * Visits every track and calls @p callback.  @p callback will get the track
2548  * data and preferences and should return 0 to continue scanning or EINTR to
2549  * stop.
2550  */
2551 int trackdb_scan(const char *root,
2552                  int (*callback)(const char *track,
2553                                  struct kvp *data,
2554                                  struct kvp *prefs,
2555                                  void *u,
2556                                  DB_TXN *tid),
2557                  void *u,
2558                  DB_TXN *tid) {
2559   DBC *cursor;
2560   DBT k, d, pd;
2561   const size_t root_len = root ? strlen(root) : 0;
2562   int err, cberr;
2563   struct kvp *data, *prefs;
2564   const char *track;
2565
2566   cursor = trackdb_opencursor(trackdb_tracksdb, tid);
2567   if(root)
2568     err = cursor->c_get(cursor, make_key(&k, root), prepare_data(&d),
2569                         DB_SET_RANGE);
2570   else {
2571     memset(&k, 0, sizeof k);
2572     err = cursor->c_get(cursor, &k, prepare_data(&d),
2573                         DB_FIRST);
2574   }
2575   while(!err) {
2576     if(!root
2577        || (k.size > root_len
2578            && !strncmp(k.data, root, root_len)
2579            && ((char *)k.data)[root_len] == '/')) {
2580       data = kvp_urldecode(d.data, d.size);
2581       if(kvp_get(data, "_path")) {
2582         track = xstrndup(k.data, k.size);
2583         /* TODO: trackdb_prefsdb is currently a DB_HASH.  This means we have to
2584          * do a lookup for every single track.  In fact this is quite quick:
2585          * with around 10,000 tracks a complete scan is around 0.3s on my
2586          * 2.2GHz Athlon.  However, if it were a DB_BTREE, we could do the same
2587          * linear walk as we already do over trackdb_tracksdb, and probably get
2588          * even higher performance.  That would require upgrade logic to
2589          * translate old databases though.
2590          */
2591         switch(err = trackdb_prefsdb->get(trackdb_prefsdb, tid, &k,
2592                                           prepare_data(&pd), 0)) {
2593         case 0:
2594           prefs = kvp_urldecode(pd.data, pd.size);
2595           break;
2596         case DB_NOTFOUND:
2597           prefs = 0;
2598           break;
2599         case DB_LOCK_DEADLOCK:
2600           disorder_error(0, "getting prefs: %s", db_strerror(err));
2601           trackdb_closecursor(cursor);
2602           return err;
2603         default:
2604           disorder_fatal(0, "getting prefs: %s", db_strerror(err));
2605         }
2606         /* Advance to the next track before the callback so that the callback
2607          * may safely delete the track */
2608         err = cursor->c_get(cursor, &k, &d, DB_NEXT);
2609         if((cberr = callback(track, data, prefs, u, tid))) {
2610           err = cberr;
2611           break;
2612         }
2613       } else
2614         err = cursor->c_get(cursor, &k, &d, DB_NEXT);
2615     } else
2616       break;
2617   }
2618   trackdb_closecursor(cursor);
2619   switch(err) {
2620   case EINTR:
2621     return err;
2622   case 0:
2623   case DB_NOTFOUND:
2624     return 0;
2625   case DB_LOCK_DEADLOCK:
2626     disorder_error(0, "c->c_get: %s", db_strerror(err));
2627     return err;
2628   default:
2629     disorder_fatal(0, "c->c_get: %s", db_strerror(err));
2630   }
2631 }
2632
2633 /* trackdb_rescan ************************************************************/
2634
2635 /** @brief Node in the list of rescan-complete callbacks */
2636 struct rescanned_node {
2637   struct rescanned_node *next;
2638   void (*rescanned)(void *ru);
2639   void *ru;
2640 };
2641
2642 /** @brief List of rescan-complete callbacks */
2643 static struct rescanned_node *rescanned_list;
2644
2645 /** @brief Add a rescan completion callback */
2646 void trackdb_add_rescanned(void (*rescanned)(void *ru),
2647                            void *ru) {
2648   if(rescanned) {
2649     struct rescanned_node *n = xmalloc(sizeof *n);
2650     n->next = rescanned_list;
2651     n->rescanned = rescanned;
2652     n->ru = ru;
2653     rescanned_list = n;
2654   }
2655 }
2656
2657 /* called when the rescanner terminates */
2658 static int reap_rescan(ev_source attribute((unused)) *ev,
2659                        pid_t pid,
2660                        int status,
2661                        const struct rusage attribute((unused)) *rusage,
2662                        void attribute((unused)) *u) {
2663   if(pid == rescan_pid) rescan_pid = -1;
2664   if(status)
2665     disorder_error(0, RESCAN": %s", wstat(status));
2666   else
2667     D((RESCAN" terminated: %s", wstat(status)));
2668   /* Our cache of file lookups is out of date now */
2669   cache_clean(&cache_files_type);
2670   eventlog("rescanned", (char *)0);
2671   /* Call rescanned callbacks */
2672   while(rescanned_list) {
2673     void (*rescanned)(void *u_) = rescanned_list->rescanned;
2674     void *ru = rescanned_list->ru;
2675
2676     rescanned_list = rescanned_list->next;
2677     rescanned(ru);
2678   }
2679   return 0;
2680 }
2681
2682 /** @brief Initiate a rescan
2683  * @param ev Event loop or 0 to block
2684  * @param recheck 1 to recheck lengths, 0 to suppress check
2685  * @param rescanned Called on completion (if not NULL)
2686  * @param ru Passed to @p rescanned
2687  */
2688 void trackdb_rescan(ev_source *ev, int recheck,
2689                     void (*rescanned)(void *ru),
2690                     void *ru) {
2691   int w;
2692
2693   if(rescan_pid != -1) {
2694     trackdb_add_rescanned(rescanned, ru);
2695     disorder_error(0, "rescan already underway");
2696     return;
2697   }
2698   rescan_pid = subprogram(ev, -1, RESCAN,
2699                           recheck ? "--check" : "--no-check",
2700                           (char *)0);
2701   trackdb_add_rescanned(rescanned, ru);
2702   if(ev) {
2703     ev_child(ev, rescan_pid, 0, reap_rescan, 0);
2704     D(("started rescanner"));
2705   } else {
2706     /* This is the first rescan, we block until it is complete */
2707     while(waitpid(rescan_pid, &w, 0) < 0 && errno == EINTR)
2708       ;
2709     reap_rescan(0, rescan_pid, w, 0, 0);
2710   }
2711 }
2712
2713 /** @brief Cancel a rescan
2714  * @return Nonzero if a rescan was cancelled
2715  */
2716 int trackdb_rescan_cancel(void) {
2717   if(rescan_pid == -1) return 0;
2718   if(kill(rescan_pid, SIGTERM) < 0)
2719     disorder_fatal(errno, "error killing rescanner");
2720   rescan_pid = -1;
2721   return 1;
2722 }
2723
2724 /** @brief Return true if a rescan is underway */
2725 int trackdb_rescan_underway(void) {
2726   return rescan_pid != -1;
2727 }
2728
2729 /* global prefs **************************************************************/
2730
2731 /** @brief Set a global preference
2732  * @param name Global preference name
2733  * @param value New value
2734  * @param who Who is setting it
2735  */
2736 void trackdb_set_global(const char *name,
2737                         const char *value,
2738                         const char *who) {
2739   DB_TXN *tid;
2740   int err;
2741   int state;
2742
2743   for(;;) {
2744     tid = trackdb_begin_transaction();
2745     if(!(err = trackdb_set_global_tid(name, value, tid)))
2746       break;
2747     trackdb_abort_transaction(tid);
2748   }
2749   trackdb_commit_transaction(tid);
2750   /* log important state changes */
2751   if(!strcmp(name, "playing")) {
2752     state = !value || !strcmp(value, "yes");
2753     disorder_info("playing %s by %s",
2754                   state ? "enabled" : "disabled",
2755                   who ? who : "-");
2756     eventlog("state", state ? "enable_play" : "disable_play", (char *)0);
2757   }
2758   if(!strcmp(name, "random-play")) {
2759     state = !value || !strcmp(value, "yes");
2760     disorder_info("random play %s by %s",
2761                   state ? "enabled" : "disabled",
2762                   who ? who : "-");
2763     eventlog("state", state ? "enable_random" : "disable_random", (char *)0);
2764   }
2765 }
2766
2767 /** @brief Set a global preference
2768  * @param name Global preference name
2769  * @param value New value
2770  * @param tid Owning transaction
2771  */
2772 int trackdb_set_global_tid(const char *name,
2773                            const char *value,
2774                            DB_TXN *tid) {
2775   DBT k, d;
2776   int err;
2777
2778   memset(&k, 0, sizeof k);
2779   memset(&d, 0, sizeof d);
2780   k.data = (void *)name;
2781   k.size = strlen(name);
2782   if(value) {
2783     d.data = (void *)value;
2784     d.size = strlen(value);
2785   }
2786   if(value)
2787     err = trackdb_globaldb->put(trackdb_globaldb, tid, &k, &d, 0);
2788   else
2789     err = trackdb_globaldb->del(trackdb_globaldb, tid, &k, 0);
2790   if(err == DB_LOCK_DEADLOCK) return err;
2791   if(err)
2792     disorder_fatal(0, "error updating database: %s", db_strerror(err));
2793   return 0;
2794 }
2795
2796 /** @brief Get a global preference
2797  * @param name Global preference name
2798  * @return Value of global preference, or NULL if it's not set
2799  */
2800 const char *trackdb_get_global(const char *name) {
2801   DB_TXN *tid;
2802   int err;
2803   const char *r;
2804
2805   for(;;) {
2806     tid = trackdb_begin_transaction();
2807     if(!(err = trackdb_get_global_tid(name, tid, &r)))
2808       break;
2809     trackdb_abort_transaction(tid);
2810   }
2811   trackdb_commit_transaction(tid);
2812   return r;
2813 }
2814
2815 /** @brief Get a global preference
2816  * @param name Global preference name
2817  * @param tid Owning transaction
2818  * @param rp Where to store value (will get NULL if preference not set)
2819  * @return 0 or DB_LOCK_DEADLOCK
2820  */
2821 int trackdb_get_global_tid(const char *name,
2822                            DB_TXN *tid,
2823                            const char **rp) {
2824   DBT k, d;
2825   int err;
2826
2827   memset(&k, 0, sizeof k);
2828   k.data = (void *)name;
2829   k.size = strlen(name);
2830   switch(err = trackdb_globaldb->get(trackdb_globaldb, tid, &k,
2831                                      prepare_data(&d), 0)) {
2832   case 0:
2833     *rp = xstrndup(d.data, d.size);
2834     return 0;
2835   case DB_NOTFOUND:
2836     *rp = 0;
2837     return 0;
2838   case DB_LOCK_DEADLOCK:
2839     return err;
2840   default:
2841     disorder_fatal(0, "error reading database: %s", db_strerror(err));
2842   }
2843 }
2844
2845 /** @brief Retrieve the most recently added tracks
2846  * @param ntracksp Where to put count, or 0
2847  * @param maxtracks Maximum number of tracks to retrieve
2848  * @return null-terminated array of track names
2849  *
2850  * The most recently added track is first in the array.
2851  */
2852 char **trackdb_new(int *ntracksp,
2853                    int maxtracks) {
2854   DB_TXN *tid;
2855   char **tracks;
2856
2857   for(;;) {
2858     tid = trackdb_begin_transaction();
2859     tracks = trackdb_new_tid(ntracksp, maxtracks, tid);
2860     if(tracks)
2861       break;
2862     trackdb_abort_transaction(tid);
2863   }
2864   trackdb_commit_transaction(tid);
2865   return tracks;
2866 }
2867
2868 /** @brief Retrieve the most recently added tracks
2869  * @param ntracksp Where to put count, or 0
2870  * @param maxtracks Maximum number of tracks to retrieve, or 0 for all
2871  * @param tid Transaction ID
2872  * @return null-terminated array of track names, or NULL on deadlock
2873  *
2874  * The most recently added track is first in the array.
2875  */
2876 static char **trackdb_new_tid(int *ntracksp,
2877                               int maxtracks,
2878                               DB_TXN *tid) {
2879   DBC *c;
2880   DBT k, d;
2881   int err = 0;
2882   struct vector tracks[1];
2883   hash *h = hash_new(1);
2884
2885   vector_init(tracks);
2886   c = trackdb_opencursor(trackdb_noticeddb, tid);
2887   while((maxtracks <= 0 || tracks->nvec < maxtracks)
2888         && !(err = c->c_get(c, prepare_data(&k), prepare_data(&d), DB_PREV))) {
2889     char *const track = xstrndup(d.data, d.size);
2890     /* Don't add any track more than once */
2891     if(hash_add(h, track, "", HASH_INSERT))
2892       continue;
2893     /* See if the track still exists */
2894     err = trackdb_getdata(trackdb_tracksdb, track, NULL/*kp*/, tid);
2895     if(err == DB_NOTFOUND)
2896       continue;                         /* It doesn't, skip it */
2897     if(err == DB_LOCK_DEADLOCK)
2898       break;                            /* Doh */
2899     vector_append(tracks, track);
2900   }
2901   switch(err) {
2902   case 0:                               /* hit maxtracks */
2903   case DB_NOTFOUND:                     /* ran out of tracks */
2904     break;
2905   case DB_LOCK_DEADLOCK:
2906     trackdb_closecursor(c);
2907     return 0;
2908   default:
2909     disorder_fatal(0, "error reading noticed.db: %s", db_strerror(err));
2910   }
2911   if((err = trackdb_closecursor(c)))
2912     return 0;                           /* deadlock */
2913   vector_terminate(tracks);
2914   if(ntracksp)
2915     *ntracksp = tracks->nvec;
2916   return tracks->vec;
2917 }
2918
2919 /** @brief Expire noticed.db
2920  * @param earliest Earliest timestamp to keep
2921  */
2922 void trackdb_expire_noticed(time_t earliest) {
2923   DB_TXN *tid;
2924
2925   for(;;) {
2926     tid = trackdb_begin_transaction();
2927     if(!trackdb_expire_noticed_tid(earliest, tid))
2928       break;
2929     trackdb_abort_transaction(tid);
2930   }
2931   trackdb_commit_transaction(tid);
2932 }
2933
2934 /** @brief Expire noticed.db
2935  * @param earliest Earliest timestamp to keep
2936  * @param tid Transaction ID
2937  * @return 0 or DB_LOCK_DEADLOCK
2938  */
2939 static int trackdb_expire_noticed_tid(time_t earliest, DB_TXN *tid) {
2940   DBC *c;
2941   DBT k, d;
2942   int err = 0, ret;
2943   time_t when;
2944   uint32_t *kk;
2945   int count = 0;
2946
2947   c = trackdb_opencursor(trackdb_noticeddb, tid);
2948   while(!(err = c->c_get(c, prepare_data(&k), prepare_data(&d), DB_NEXT))) {
2949     kk = k.data;
2950     when = (time_t)(((uint64_t)ntohl(kk[0]) << 32) + ntohl(kk[1]));
2951     if(when >= earliest)
2952       break;
2953     if((err = c->c_del(c, 0))) {
2954       if(err != DB_LOCK_DEADLOCK)
2955         disorder_fatal(0, "error deleting expired noticed.db entry: %s",
2956                        db_strerror(err));
2957       break;
2958     }
2959     ++count;
2960   }
2961   if(err == DB_NOTFOUND)
2962     err = 0;
2963   if(err && err != DB_LOCK_DEADLOCK)
2964     disorder_fatal(0, "error expiring noticed.db: %s", db_strerror(err));
2965   ret = err;
2966   if((err = trackdb_closecursor(c))) {
2967     if(err != DB_LOCK_DEADLOCK)
2968       disorder_fatal(0, "error closing cursor: %s", db_strerror(err));
2969     ret = err;
2970   }
2971   if(!ret && count)
2972     disorder_info("expired %d tracks from noticed.db", count);
2973   return ret;
2974 }
2975
2976 /* tidying up ****************************************************************/
2977
2978 /** @brief Do database garbage collection
2979  *
2980  * Called form periodic_database_gc().
2981  */
2982 void trackdb_gc(void) {
2983   int err;
2984   char **logfiles;
2985
2986   if((err = trackdb_env->txn_checkpoint(trackdb_env,
2987                                         config->checkpoint_kbyte,
2988                                         config->checkpoint_min,
2989                                         0)))
2990     disorder_fatal(0, "trackdb_env->txn_checkpoint: %s", db_strerror(err));
2991   if((err = trackdb_env->log_archive(trackdb_env, &logfiles, DB_ARCH_REMOVE)))
2992     disorder_fatal(0, "trackdb_env->log_archive: %s", db_strerror(err));
2993   /* This makes catastrophic recovery impossible.  However, the user can still
2994    * preserve the important data by using disorder-dump to snapshot their
2995    * prefs, and later to restore it.  This is likely to have much small
2996    * long-term storage requirements than record the db logfiles. */
2997 }
2998
2999 /* user database *************************************************************/
3000
3001 /** @brief Return true if @p user is trusted
3002  * @param user User to look up
3003  * @return Nonzero if they are in the 'trusted' list
3004  *
3005  * Now used only in upgrade from old versions.
3006  */
3007 static int trusted(const char *user) {
3008   int n;
3009
3010   for(n = 0; (n < config->trust.n
3011               && strcmp(config->trust.s[n], user)); ++n)
3012     ;
3013   return n < config->trust.n;
3014 }
3015
3016 /** @brief Return non-zero for a valid username
3017  * @param user Candidate username
3018  * @return Nonzero if it's valid
3019  *
3020  * Currently we only allow the letters and digits in ASCII.  We could be more
3021  * liberal than this but it is a nice simple test.  It is critical that
3022  * semicolons are never allowed.
3023  *
3024  * NB also used by playlist_parse_name() to validate playlist names!
3025  */
3026 int valid_username(const char *user) {
3027   if(!*user)
3028     return 0;
3029   while(*user) {
3030     const uint8_t c = *user++;
3031     /* For now we are very strict */
3032     if((c >= 'a' && c <= 'z')
3033        || (c >= 'A' && c <= 'Z')
3034        || (c >= '0' && c <= '9'))
3035       /* ok */;
3036     else
3037       return 0;
3038   }
3039   return 1;
3040 }
3041
3042 /** @brief Add a user
3043  * @param user Username
3044  * @param password Initial password or NULL
3045  * @param rights Initial rights
3046  * @param email Email address or NULL
3047  * @param confirmation Confirmation string to require
3048  * @param tid Owning transaction
3049  * @param flags DB flags e.g. DB_NOOVERWRITE
3050  * @return 0, DB_KEYEXIST or DB_LOCK_DEADLOCK
3051  */
3052 static int create_user(const char *user,
3053                        const char *password,
3054                        const char *rights,
3055                        const char *email,
3056                        const char *confirmation,
3057                        DB_TXN *tid,
3058                        uint32_t flags) {
3059   struct kvp *k = 0;
3060   char s[64];
3061
3062   /* sanity check user */
3063   if(!valid_username(user)) {
3064     disorder_error(0, "invalid username '%s'", user);
3065     return -1;
3066   }
3067   if(parse_rights(rights, 0, 1)) {
3068     disorder_error(0, "invalid rights string");
3069     return -1;
3070   }
3071   /* data for this user */
3072   if(password)
3073     kvp_set(&k, "password", password);
3074   kvp_set(&k, "rights", rights);
3075   if(email)
3076     kvp_set(&k, "email", email);
3077   if(confirmation)
3078     kvp_set(&k, "confirmation", confirmation);
3079   snprintf(s, sizeof s, "%jd", (intmax_t)xtime(0));
3080   kvp_set(&k, "created", s);
3081   return trackdb_putdata(trackdb_usersdb, user, k, tid, flags);
3082 }
3083
3084 /** @brief Add one pre-existing user 
3085  * @param user Username
3086  * @param password password
3087  * @param tid Owning transaction
3088  * @return 0, DB_KEYEXIST or DB_LOCK_DEADLOCK
3089  *
3090  * Used only in upgrade from old versions.
3091  */
3092 static int one_old_user(const char *user, const char *password,
3093                         DB_TXN *tid) {
3094   const char *rights;
3095
3096   /* www-data doesn't get added */
3097   if(!strcmp(user, "www-data")) {
3098     disorder_info("not adding www-data to user database");
3099     return 0;
3100   }
3101   /* pick rights */
3102   if(!strcmp(user, "root"))
3103     rights = "all";
3104   else if(trusted(user)) {
3105     rights_type r;
3106
3107     parse_rights(config->default_rights, &r, 1);
3108     r &= ~(rights_type)(RIGHT_SCRATCH__MASK|RIGHT_MOVE__MASK|RIGHT_REMOVE__MASK);
3109     r |= (RIGHT_ADMIN|RIGHT_RESCAN
3110           |RIGHT_SCRATCH_ANY|RIGHT_MOVE_ANY|RIGHT_REMOVE_ANY);
3111     rights = rights_string(r);
3112   } else
3113     rights = config->default_rights;
3114   return create_user(user, password, rights, 0/*email*/, 0/*confirmation*/,
3115                      tid, DB_NOOVERWRITE);
3116 }
3117
3118 /** @brief Upgrade old users
3119  * @param tid Owning transaction
3120  * @return 0 or DB_LOCK_DEADLOCK
3121  */
3122 static int trackdb_old_users_tid(DB_TXN *tid) {
3123   int n;
3124
3125   for(n = 0; n < config->allow.n; ++n) {
3126     switch(one_old_user(config->allow.s[n].s[0], config->allow.s[n].s[1],
3127                         tid)) {
3128     case 0:
3129       disorder_info("created user %s from 'allow' directive",
3130                     config->allow.s[n].s[0]);
3131       break;
3132     case DB_KEYEXIST:
3133       disorder_error(0, "user %s already exists, delete 'allow' directive",
3134             config->allow.s[n].s[0]);
3135           /* This won't ever become fatal - eventually 'allow' will be
3136            * disabled. */
3137       break;
3138     case DB_LOCK_DEADLOCK:
3139       return DB_LOCK_DEADLOCK;
3140     }
3141   }
3142   return 0;
3143 }
3144
3145 /** @brief Read old 'allow' directives and copy them to the users database */
3146 void trackdb_old_users(void) {
3147   int e;
3148
3149   if(config->allow.n)
3150     WITH_TRANSACTION(trackdb_old_users_tid(tid));
3151 }
3152
3153 /** @brief Create a root user in the user database if there is none */
3154 void trackdb_create_root(void) {
3155   int e;
3156   uint8_t pwbin[12];
3157   char *pw;
3158
3159   /* Choose a new root password */
3160   gcry_randomize(pwbin, sizeof pwbin, GCRY_STRONG_RANDOM);
3161   pw = mime_to_base64(pwbin, sizeof pwbin);
3162   /* Create the root user if it does not exist */
3163   WITH_TRANSACTION(create_user("root", pw, "all",
3164                                0/*email*/, 0/*confirmation*/,
3165                                tid, DB_NOOVERWRITE));
3166   if(e == 0)
3167     disorder_info("created root user");
3168 }
3169
3170 /** @brief Find a user's password from the database
3171  * @param user Username
3172  * @return Password or NULL
3173  *
3174  * Only works if running as a user that can read the database!
3175  *
3176  * If the user exists but has no password, "" is returned.
3177  */
3178 const char *trackdb_get_password(const char *user) {
3179   int e;
3180   struct kvp *k;
3181   const char *password;
3182
3183   WITH_TRANSACTION(trackdb_getdata(trackdb_usersdb, user, &k, tid));
3184   if(e)
3185     return 0;
3186   password = kvp_get(k, "password");
3187   return password ? password : "";
3188 }
3189
3190 /** @brief Add a new user
3191  * @param user Username
3192  * @param password Password or NULL
3193  * @param rights Initial rights
3194  * @param email Email address or NULL
3195  * @param confirmation Confirmation string or NULL
3196  * @return 0 on success, non-0 on error
3197  */
3198 int trackdb_adduser(const char *user,
3199                     const char *password,
3200                     const char *rights,
3201                     const char *email,
3202                     const char *confirmation) {
3203   int e;
3204
3205   WITH_TRANSACTION(create_user(user, password, rights, email, confirmation,
3206                                tid, DB_NOOVERWRITE));
3207   if(e) {
3208     disorder_error(0, "cannot create user '%s' because they already exist",
3209                    user);
3210     return -1;
3211   } else {
3212     if(email)
3213       disorder_info("created user '%s' with rights '%s' and email address '%s'",
3214                     user, rights, email);
3215     else
3216       disorder_info("created user '%s' with rights '%s'", user, rights);
3217     eventlog("user_add", user, (char *)0);
3218     return 0;
3219   }
3220 }
3221
3222 /** @brief Delete a user
3223  * @param user User to delete
3224  * @return 0 on success, non-0 if the user didn't exist anyway
3225  */
3226 int trackdb_deluser(const char *user) {
3227   int e;
3228
3229   WITH_TRANSACTION(trackdb_delkey(trackdb_usersdb, user, tid));
3230   if(e) {
3231     disorder_error(0, "cannot delete user '%s' because they do not exist",
3232                    user);
3233     return -1;
3234   }
3235   disorder_info("deleted user '%s'", user);
3236   eventlog("user_delete", user, (char *)0);
3237   return 0;
3238 }
3239
3240 /** @brief Get user information
3241  * @param user User to query
3242  * @return Linked list of user information or NULL if user does not exist
3243  *
3244  * Every user has at least a @c rights entry so NULL can be used to mean no
3245  * such user safely.
3246  */
3247 struct kvp *trackdb_getuserinfo(const char *user) {
3248   int e;
3249   struct kvp *k;
3250
3251   WITH_TRANSACTION(trackdb_getdata(trackdb_usersdb, user, &k, tid));
3252   if(e)
3253     return 0;
3254   else
3255     return k;
3256 }
3257
3258 /** @brief Edit user information
3259  * @param user User to edit
3260  * @param key Key to change
3261  * @param value Value to set, or NULL to remove
3262  * @param tid Transaction ID
3263  * @return 0, DB_LOCK_DEADLOCK or DB_NOTFOUND
3264  */
3265 static int trackdb_edituserinfo_tid(const char *user, const char *key,
3266                                     const char *value, DB_TXN *tid) {
3267   struct kvp *k;
3268   int e;
3269
3270   if((e = trackdb_getdata(trackdb_usersdb, user, &k, tid)))
3271     return e;
3272   if(!kvp_set(&k, key, value))
3273     return 0;                           /* no change */
3274   return trackdb_putdata(trackdb_usersdb, user, k, tid, 0);
3275 }
3276
3277 /** @brief Edit user information
3278  * @param user User to edit
3279  * @param key Key to change
3280  * @param value Value to set, or NULL to remove
3281  * @return 0 on success, non-0 on error
3282  */
3283 int trackdb_edituserinfo(const char *user,
3284                          const char *key, const char *value) {
3285   int e;
3286
3287   if(!strcmp(key, "rights")) {
3288     if(!value) {
3289       disorder_error(0, "cannot remove 'rights' key from user '%s'", user);
3290       return -1;
3291     }
3292     if(parse_rights(value, 0, 1)) {
3293       disorder_error(0, "invalid rights string");
3294       return -1;
3295     }
3296   } else if(!strcmp(key, "email")) {
3297     if(*value) {
3298       if(!email_valid(value)) {
3299         disorder_error(0, "invalid email address '%s' for user '%s'",
3300                        value, user);
3301         return -1;
3302       }
3303     } else
3304       value = 0;                        /* no email -> remove key */
3305   } else if(!strcmp(key, "created")) {
3306     disorder_error(0, "cannot change creation date for user '%s'", user);
3307     return -1;
3308   } else if(strcmp(key, "password")
3309             && !strcmp(key, "confirmation")) {
3310     disorder_error(0, "unknown user info key '%s' for user '%s'", key, user);
3311     return -1;
3312   }
3313   WITH_TRANSACTION(trackdb_edituserinfo_tid(user, key, value, tid));
3314   if(e) {
3315     disorder_error(0, "unknown user '%s'", user);
3316     return -1;
3317   } else {
3318     eventlog("user_edit", user, key, (char *)0);
3319     return 0;
3320   }
3321 }
3322
3323 /** @brief List all users
3324  * @return NULL-terminated list of users
3325  */
3326 char **trackdb_listusers(void) {
3327   int e;
3328   struct vector v[1];
3329
3330   vector_init(v);
3331   WITH_TRANSACTION(trackdb_listkeys(trackdb_usersdb, v, tid));
3332   return v->vec;
3333 }
3334
3335 /** @brief Confirm a user registration
3336  * @param user Username
3337  * @param confirmation Confirmation string
3338  * @param rightsp Where to put user rights
3339  * @param tid Transaction ID
3340  * @return 0 on success, non-0 on error
3341  */
3342 static int trackdb_confirm_tid(const char *user, const char *confirmation,
3343                                rights_type *rightsp,
3344                                DB_TXN *tid) {
3345   const char *stored_confirmation;
3346   struct kvp *k;
3347   int e;
3348   const char *rights;
3349   
3350   if((e = trackdb_getdata(trackdb_usersdb, user, &k, tid)))
3351     return e;
3352   if(!(stored_confirmation = kvp_get(k, "confirmation"))) {
3353     disorder_error(0, "already confirmed user '%s'", user);
3354     /* DB claims -30,800 to -30,999 so -1 should be a safe bet */
3355     return -1;
3356   }
3357   if(!(rights = kvp_get(k, "rights"))) {
3358     disorder_error(0, "no rights for unconfirmed user '%s'", user);
3359     return -1;
3360   }
3361   if(parse_rights(rights, rightsp, 1))
3362     return -1;
3363   if(strcmp(confirmation, stored_confirmation)) {
3364     disorder_error(0, "wrong confirmation string for user '%s'", user);
3365     return -1;
3366   }
3367   /* 'sall good */
3368   kvp_set(&k, "confirmation", 0);
3369   return trackdb_putdata(trackdb_usersdb, user, k, tid, 0);
3370 }
3371
3372 /** @brief Confirm a user registration
3373  * @param user Username
3374  * @param confirmation Confirmation string
3375  * @param rightsp Where to put user rights
3376  * @return 0 on success, non-0 on error
3377  */
3378 int trackdb_confirm(const char *user, const char *confirmation,
3379                     rights_type *rightsp) {
3380   int e;
3381
3382   WITH_TRANSACTION(trackdb_confirm_tid(user, confirmation, rightsp, tid));
3383   switch(e) {
3384   case 0:
3385     disorder_info("registration confirmed for user '%s'", user);
3386     eventlog("user_confirm", user, (char *)0);
3387     return 0;
3388   case DB_NOTFOUND:
3389     disorder_error(0, "confirmation for nonexistent user '%s'", user);
3390     return -1;
3391   default:                              /* already reported */
3392     return -1;
3393   }
3394 }
3395
3396 /*
3397 Local Variables:
3398 c-basic-offset:2
3399 comment-column:40
3400 fill-column:79
3401 indent-tabs-mode:nil
3402 End:
3403 */