X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/disorder/blobdiff_plain/de3bd7adcd70035ee61df815033cceeb7b7abc32..375d9478a5b6b14bfb5f6e1a054e900a18e40717:/server/dbupgrade.c diff --git a/server/dbupgrade.c b/server/dbupgrade.c index b856ae5..18e6aa1 100644 --- a/server/dbupgrade.c +++ b/server/dbupgrade.c @@ -1,44 +1,26 @@ /* * This file is part of DisOrder - * Copyright (C) 2007 Richard Kettlewell + * Copyright (C) 2007, 2008 Richard Kettlewell * - * This program is free software; you can redistribute it and/or modify + * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or + * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA + * along with this program. If not, see . */ - -#include -#include "types.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "syscalls.h" -#include "log.h" -#include "defs.h" -#include "kvp.h" -#include "trackdb.h" -#include "trackdb-int.h" -#include "mem.h" -#include "configuration.h" -#include "unicode.h" +/** @file server/dbupgrade.c + * @brief Database upgrade utility + * + * Invoked by the server when necessary. + */ +#include "disorder-server.h" static DB_TXN *global_tid; @@ -84,13 +66,6 @@ static void help(void) { exit(0); } -/* display version number and terminate */ -static void version(void) { - xprintf("disorder-dbupgrade version %s\n", disorder_version_string); - xfclose(stdout); - exit(0); -} - /** @brief Visit each key in a database and call @p callback * @return 0 or DB_LOCK_DEADLOCK * @@ -117,24 +92,24 @@ static int scan_core(const char *name, DB *db, break; ++count; if(count % 1000 == 0) - info("scanning %s, %ld so far", name, count); + disorder_info("scanning %s, %ld so far", name, count); } if(err && err != DB_NOTFOUND && err != DB_LOCK_DEADLOCK) - fatal(0, "%s: error scanning database: %s", name, db_strerror(err)); + disorder_fatal(0, "%s: error scanning database: %s", name, db_strerror(err)); r = (err == DB_LOCK_DEADLOCK ? err : 0); if((err = c->c_close(c))) - fatal(0, "%s: error closing cursor: %s", name, db_strerror(err)); - info("%s: %ld entries scanned", name, count); + disorder_fatal(0, "%s: error closing cursor: %s", name, db_strerror(err)); + disorder_info("%s: %ld entries scanned", name, count); if(values_normalized || values_already_ok) - info("%s: %ld values converted, %ld already ok", name, - values_normalized, values_already_ok); + disorder_info("%s: %ld values converted, %ld already ok", name, + values_normalized, values_already_ok); if(keys_normalized || keys_already_ok) - info("%s: %ld keys converted, %ld already OK", name, - keys_normalized, keys_already_ok); + disorder_info("%s: %ld keys converted, %ld already OK", name, + keys_normalized, keys_already_ok); if(aliases_removed) - info("%s: %ld aliases removed", name, aliases_removed); + disorder_info("%s: %ld aliases removed", name, aliases_removed); if(renoticed) - info("%s: %ld tracks re-noticed", name, renoticed); + disorder_info("%s: %ld tracks re-noticed", name, renoticed); return r; } @@ -143,16 +118,16 @@ static int scan_core(const char *name, DB *db, * Everything happens inside the @p global_tid tranasction. @p callback * should return 0 or DB_LOCK_DEADLOCK. */ -static void scan(const char *name, DB *db, - int (*callback)(const char *name, DB *db, DBC *c, - DBT *k, DBT *d)) { - info("scanning %s", name); +static void scandb(const char *name, DB *db, + int (*callback)(const char *name, DB *db, DBC *c, + DBT *k, DBT *d)) { + disorder_info("scanning %s", name); for(;;) { global_tid = trackdb_begin_transaction(); if(scan_core(name, db, callback)) { trackdb_abort_transaction(global_tid); global_tid = 0; - error(0, "detected deadlock, restarting scan"); + disorder_error(0, "detected deadlock, restarting scan"); continue; } else { trackdb_commit_transaction(global_tid); @@ -171,7 +146,7 @@ static void truncate_database(const char *name, DB *db) { err = db->truncate(db, 0, &count, DB_AUTO_COMMIT); } while(err == DB_LOCK_DEADLOCK); if(err) - fatal(0, "error truncating %s: %s", name, db_strerror(err)); + disorder_fatal(0, "error truncating %s: %s", name, db_strerror(err)); } /* scan callbacks */ @@ -187,22 +162,22 @@ static int normalize_keys(const char *name, DB *db, DBC *c, if(!knfc) { switch(badkey) { case BADKEY_WARN: - error(0, "%s: invalid key: %.*s", name, - (int)k->size, (const char *)k->data); + disorder_error(0, "%s: invalid key: %.*s", name, + (int)k->size, (const char *)k->data); break; case BADKEY_DELETE: - error(0, "%s: deleting invalid key: %.*s", name, - (int)k->size, (const char *)k->data); + disorder_error(0, "%s: deleting invalid key: %.*s", name, + (int)k->size, (const char *)k->data); if((err = c->c_del(c, 0))) { if(err != DB_LOCK_DEADLOCK) - fatal(0, "%s: error removing denormalized key: %s", - name, db_strerror(err)); + disorder_fatal(0, "%s: error removing denormalized key: %s", + name, db_strerror(err)); return err; } break; case BADKEY_FAIL: - fatal(0, "%s: invalid key: %.*s", name, - (int)k->size, (const char *)k->data); + disorder_fatal(0, "%s: invalid key: %.*s", name, + (int)k->size, (const char *)k->data); } return 0; } @@ -214,15 +189,16 @@ static int normalize_keys(const char *name, DB *db, DBC *c, /* To rename the key we must delete the old one and insert a new one */ if((err = c->c_del(c, 0))) { if(err != DB_LOCK_DEADLOCK) - fatal(0, "%s: error removing denormalized key: %s", - name, db_strerror(err)); + disorder_fatal(0, "%s: error removing denormalized key: %s", + name, db_strerror(err)); return err; } k->size = nknfc; k->data = knfc; if((err = db->put(db, global_tid, k, d, DB_NOOVERWRITE))) { if(err != DB_LOCK_DEADLOCK) - fatal(0, "%s: error storing normalized key: %s", name, db_strerror(err)); + disorder_fatal(0, "%s: error storing normalized key: %s", + name, db_strerror(err)); return err; } ++keys_normalized; @@ -239,8 +215,8 @@ static int normalize_values(const char *name, DB *db, /* Find the normalized form of the value */ dnfc = utf8_compose_canon(d->data, d->size, &ndnfc); if(!dnfc) - fatal(0, "%s: cannot convert data to NFC: %.*s", name, - (int)d->size, (const char *)d->data); + disorder_fatal(0, "%s: cannot convert data to NFC: %.*s", name, + (int)d->size, (const char *)d->data); /* If the key is already in NFC then do nothing */ if(ndnfc == d->size && !memcmp(d->data, dnfc, ndnfc)) { ++values_already_ok; @@ -250,7 +226,8 @@ static int normalize_values(const char *name, DB *db, d->data = dnfc; if((err = db->put(db, global_tid, k, d, 0))) { if(err != DB_LOCK_DEADLOCK) - fatal(0, "%s: error storing normalized data: %s", name, db_strerror(err)); + disorder_fatal(0, "%s: error storing normalized data: %s", + name, db_strerror(err)); return err; } ++values_normalized; @@ -270,8 +247,8 @@ static int renotice(const char *name, DB attribute((unused)) *db, * in the scan. */ if(kvp_get(t, "_alias_for")) return 0; - fatal(0, "%s: no '_path' for %.*s", name, - (int)k->size, (const char *)k->data); + disorder_fatal(0, "%s: no '_path' for %.*s", name, + (int)k->size, (const char *)k->data); } switch(err = trackdb_notice_tid(track, path, global_tid)) { case 0: @@ -280,8 +257,8 @@ static int renotice(const char *name, DB attribute((unused)) *db, case DB_LOCK_DEADLOCK: return err; default: - fatal(0, "%s: unexpected return from trackdb_notice_tid: %s", - name, db_strerror(err)); + disorder_fatal(0, "%s: unexpected return from trackdb_notice_tid: %s", + name, db_strerror(err)); } } @@ -294,14 +271,14 @@ static int remove_aliases_normalize_keys(const char *name, DB *db, DBC *c, /* This is an alias. We remove all the alias entries. */ if((err = c->c_del(c, 0))) { if(err != DB_LOCK_DEADLOCK) - fatal(0, "%s: error removing alias: %s", name, db_strerror(err)); + disorder_fatal(0, "%s: error removing alias: %s", name, db_strerror(err)); return err; } ++aliases_removed; return 0; } else if(!kvp_get(t, "_path")) - error(0, "%s: %.*s has neither _alias_for nor _path", name, - (int)k->size, (const char *)k->data); + disorder_error(0, "%s: %.*s has neither _alias_for nor _path", name, + (int)k->size, (const char *)k->data); return normalize_keys(name, db, c, k, d); } @@ -313,24 +290,24 @@ static int remove_aliases_normalize_keys(const char *name, DB *db, DBC *c, static void upgrade(void) { char buf[32]; - info("upgrading database to dbversion %ld", config->dbversion); + disorder_info("upgrading database to dbversion %ld", config->dbversion); /* Normalize keys and values as required. We will also remove aliases as * they will be regenerated when we re-noticed the tracks. */ - info("renormalizing keys"); - scan("tracks.db", trackdb_tracksdb, remove_aliases_normalize_keys); - scan("prefs.db", trackdb_prefsdb, normalize_keys); - scan("global.db", trackdb_globaldb, normalize_keys); - scan("noticed.db", trackdb_noticeddb, normalize_values); + disorder_info("renormalizing keys"); + scandb("tracks.db", trackdb_tracksdb, remove_aliases_normalize_keys); + scandb("prefs.db", trackdb_prefsdb, normalize_keys); + scandb("global.db", trackdb_globaldb, normalize_keys); + scandb("noticed.db", trackdb_noticeddb, normalize_values); /* search.db and tags.db we will rebuild */ - info("regenerating search database and aliases"); + disorder_info("regenerating search database and aliases"); truncate_database("search.db", trackdb_searchdb); truncate_database("tags.db", trackdb_tagsdb); /* Regenerate the search database and aliases */ - scan("tracks.db", trackdb_tracksdb, renotice); + scandb("tracks.db", trackdb_tracksdb, renotice); /* Finally update the database version */ snprintf(buf, sizeof buf, "%ld", config->dbversion); trackdb_set_global("_dbversion", buf, 0); - info("completed database upgrade"); + disorder_info("completed database upgrade"); } int main(int argc, char **argv) { @@ -338,11 +315,11 @@ int main(int argc, char **argv) { set_progname(argv); mem_init(); - if(!setlocale(LC_CTYPE, "")) fatal(errno, "error calling setlocale"); + if(!setlocale(LC_CTYPE, "")) disorder_fatal(errno, "error calling setlocale"); while((n = getopt_long(argc, argv, "hVc:dDSsxX", options, 0)) >= 0) { switch(n) { case 'h': help(); - case 'V': version(); + case 'V': version("disorder-dbupgrade"); case 'c': configfile = optarg; break; case 'd': debugging = 1; break; case 'D': debugging = 0; break; @@ -350,7 +327,7 @@ int main(int argc, char **argv) { case 's': logsyslog = 1; break; case 'x': badkey = BADKEY_DELETE; break; case 'X': badkey = BADKEY_FAIL; break; - default: fatal(0, "invalid option"); + default: disorder_fatal(0, "invalid option"); } } /* If stderr is a TTY then log there, otherwise to syslog. */ @@ -358,7 +335,7 @@ int main(int argc, char **argv) { openlog(progname, LOG_PID, LOG_DAEMON); log_default = &log_syslog; } - if(config_read(0)) fatal(0, "cannot read configuration"); + if(config_read(0, NULL)) disorder_fatal(0, "cannot read configuration"); /* Open the database */ trackdb_init(TRACKDB_NO_RECOVER); trackdb_open(TRACKDB_OPEN_FOR_UPGRADE);