2007年4月17日火曜日

mt-daapdが起動できない

 Debian(etch)をdist-upgradeしたら、mt-daapdを起動できなくなった。

 まず、APT HOWTO 第 6 章 - ソースパッケージでの作業を参考にパッケージを再コンパイルしてみる。
fakerootツールをインストールする。

# apt-get install fakeroot
mt-daapdのソースとコンパイルに必要なパッケージをインストールする。
# apt-get source mt-daapd
# apt-get build-dep mt-daapd
mt-daapd_0.2.4+r1376.orig.tar.gz, mt-daapd_0.2.4+r1376-1.dsc, mt-daapd_0.2.4+r1376-1.diff.gzの3つがダウンロードされ展開されてコンパイル用のディレクトリィができる。そのディレクトリィに移動して以下のコマンドでパッケージを作成する。
# dpkg-buildpackage -rfakeroot -uc -b
パッケージは最初にソースをダウンロードしたディレクトリィ(1つ上)にできる。
aptでできたパッケージをインストールしてみたが、結果は変わらない。

 ログに何か出力されていないかどうか/var/log下のファイルを調べてみた。messages.logに関係ありそうなログがあった。

Mar 18 20:26:13 gold mt-daapd[4524]: *** WARNING *** The programme 'mt-daapd' uses the HOWL compatiblity layer of Avahi.
Mar 18 20:26:13 gold mt-daapd[4524]: *** WARNING *** Please fix your application to use the native API of Avahi!
Mar 18 20:26:13 gold mt-daapd[4524]: *** WARNING *** For more information see <http://0pointer.de/avahi-compat?s=howl&e=mt-daapd>
上記のURLを見てみると、AvahiはDNS Service Discoveryと Multicast DNSのライブラリ。他にもhowlという同じ機能を提供する別のライブラリもあり、Avahiは完全ではないがその互換APIを提供している。mt-daapdはAvahiのhowl互換APIを使っているのでAvahiネイティブのAPIを使うように警告を出しているということのようだ。これで起動できなくなる問題というわけではなさそう。

 さらにログを調べてみると、daemon.logにmt-daapdが出力しているエラーを見つけた。

Error opening db: No backend database support for type: sqlite
上記メッセージでmt-daapdのソース内をgrepをかけたところ、main.c内でエラーメッセージを出力しているところを見つけた。
   /* this will require that the db be readable by the runas user */
    db_type = conf_alloc_string("general","db_type","sqlite");
    db_parms = conf_alloc_string("general","db_parms","/var/cache/mt-daapd");
    err=db_open(&perr,db_type,db_parms);

    if(err) {
        DPRINTF(E_LOG,L_MAIN|L_DB,"Error opening db: %s\n",perr);
#ifndef WITHOUT_MDNS
        if(config.use_mdns) {
            rend_stop();
        }
#endif
        os_deinit();
        exit(EXIT_FAILURE);
    }
エラーメッセージは、db_open関数が失敗したときに出力されている。db_open関数はdb-generic.cにあった。
/**

 * Open the database.  This is done before we drop privs, that  * way if the database only has root perms, then it can still  * be opened.
 *
 * \param parameters This is backend-specific (mysql, sqlite, etc)
 */
int db_open(char **pe, char *type, char *parameters) {
    int result;
    DPRINTF(E_DBG,L_DB,"Opening database\n");
    if(pthread_once(&db_initlock,db_init_once))
        return -1;
    db_current = &db_functions[0];
    if(type) {
        while((db_current->name) && (strcasecmp(db_current->name,type))) {
            db_current++;
        }

        if(!db_current->name) {
            /* end of list -- no match */
            db_get_error(pe,DB_E_BADPROVIDER,type);
            return DB_E_BADPROVIDER;
        }
    }
    result=db_current->dbs_open(pe, parameters);
    DPRINTF(E_DBG,L_DB,"Results: %d\n",result);
    return result;
}
db_functions配列から第2引数のtypeと名前が一致するものを検索し、db_functionsのdbs_open関数を呼んでいる。db_functionsの型はDB_FUNCTIONSで、構造体は以下のようになっている。
/** pointers to database-specific functions */
typedef struct tag_db_functions {
    char *name;
    int(*dbs_open)(char **, char *);
    int(*dbs_init)(int*);
    int(*dbs_deinit)(void);
    int(*dbs_add)(char **, MP3FILE*, int*);
    int(*dbs_add_playlist)(char **, char *, int, char *,char *, int, int *);
    int(*dbs_add_playlist_item)(char **, int, int);
    int(*dbs_delete_playlist)(char **, int);
    int(*dbs_delete_playlist_item)(char **, int, int);
    int(*dbs_edit_playlist)(char **, int, char*, char*);
    int(*dbs_playcount_increment)(char **, int);
    int(*dbs_enum_start)(char **, DBQUERYINFO *);
    int(*dbs_enum_size)(char **, DBQUERYINFO *, int *, int *);
    int(*dbs_enum_fetch)(char **, DBQUERYINFO *, int *, unsigned char **);
    int(*dbs_enum_fetch_row)(char **, PACKED_MP3FILE *, DBQUERYINFO *);
    int(*dbs_enum_reset)(char **, DBQUERYINFO *);
    int(*dbs_enum_end)(char **);
    int(*dbs_force_rescan)(char **);
    int(*dbs_start_scan)(void);
    int(*dbs_end_song_scan)(void);
    int(*dbs_end_scan)(void);
    int(*dbs_get_count)(char **, int *, CountType_t);
    MP3FILE*(*dbs_fetch_item)(char **, int);
    MP3FILE*(*dbs_fetch_path)(char **, char *,int);
    M3UFILE*(*dbs_fetch_playlist)(char **, char *, int);
    void(*dbs_dispose_item)(MP3FILE*);
    void(*dbs_dispose_playlist)(M3UFILE*);
}DB_FUNCTIONS;
データベースごとのルーチンを格納している関数テーブルのようだ。
main.cに戻り、db_typeがどのように指定されているか確認してみる。

db_type = conf_alloc_string("general","db_type","sqlite");

でdb_typeが代入されている。
conf_alloc_stringはconf.cにあった。
/**
 * return the value from the CURRENT config tree as an allocated string  *
 * @param section section name to search in  * @param key key to search for  * @param dflt default value to return if key not found  * @returns a pointer to an allocated string containing the required  *          configuration key  */
char *conf_alloc_string(char *section, char *key, char *dflt) {
    LL_ITEM *pitem;
    char *result;
    char *retval;

    _conf_lock();
    pitem = _conf_fetch_item(conf_main,section,key);
    if((!pitem) || (pitem->type != LL_TYPE_STRING)) {
        result = dflt;
    } else {
        result = pitem->value.as_string;
    }

    if(result == NULL) {
        _conf_unlock();
        return NULL;
    }

    retval = strdup(result);

    if(!retval) {
        DPRINTF(E_FATAL,L_CONF,"Malloc error in conf_alloc_string\n");
    }
    _conf_unlock();
    return retval;
}
コンフィグファイルからkeyの値を持ってくるが、keyが存在しない場合はdfltを値としている。コンフィグファイルである/etc/mt-daapd.confにはdb_typeというkeyは存在しないので、dlftであるsqliteがdb_typeとなる。(daemon.logに書いてあるとおり)
db_functionsの中身は以下のようになっている。
DB_FUNCTIONS db_functions[] = {
#ifdef HAVE_LIBSQLITE     {
        "sqlite",
        db_sql_open_sqlite2,
        db_sql_init,
        (省略)
     },
#endif #ifdef HAVE_LIBSQLITE3     {
        "sqlite3",
        db_sql_open_sqlite3,
        db_sql_init,
        (省略)
    }
sqliteの場合はDBのオープンにdb_sql_open_sqlitesqlite2という関数を使うようになっている。関数名から推測するに、おそらくsqlite2に含まれる関数だと思われる。
で、現在システムにインストールされているsqliteを調べてみた。
# dpkg -l "*sqlite*"

+++-================-================-================================================
un gda2-sqlite      <なし>         (説明 (description) がありません)
ii libsqlite0       2.8.17-2         SQLite shared library
ii libsqlite3-0     3.3.8-1.1        SQLite 3 shared library
ii libsqlite3-dev   3.3.8-1.1        SQLite 3 development files
un sqlite3-doc      <なし>         (説明 (description) がありません)
バイナリはlibsqlite0とlibsqlite3がインストールされているが、sqlite2はインストールされていない。db_functionsからdb_typeをsqlite3にすればsqlite3のライブラリを使うようになることがわかる。また、今までの解析からdb_typeをsqlite3にするためには、mt-daapd.confに以下の行を追加すればよいこともわかる。
(/etc/mt-daapd.confの適当な場所に追加)

db_type sqlite3
これでmt-daapdを起動してみたところ、正常に動作した。

0 件のコメント: