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つがダウンロードされ展開されてコンパイル用のディレクトリィができる。そのディレクトリィに移動して以下のコマンドでパッケージを作成する。
# apt-get build-dep mt-daapd
# 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を使うように警告を出しているということのようだ。これで起動できなくなる問題というわけではなさそう。
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>
さらにログを調べてみると、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にあった。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);
}
/**
* 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で、構造体は以下のようになっている。* 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;
}
/** 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;
データベースごとのルーチンを格納している関数テーブルのようだ。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に書いてあるとおり)* 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;
}
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に含まれる関数だと思われる。#ifdef HAVE_LIBSQLITE {
"sqlite",
db_sql_open_sqlite2,
db_sql_init,
(省略)
},
#endif #ifdef HAVE_LIBSQLITE3 {
"sqlite3",
db_sql_open_sqlite3,
db_sql_init,
(省略)
}
で、現在システムにインストールされている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に以下の行を追加すればよいこともわかる。
+++-================-================-================================================
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) がありません)
(/etc/mt-daapd.confの適当な場所に追加)
db_type sqlite3
これでmt-daapdを起動してみたところ、正常に動作した。
db_type sqlite3
0 件のコメント:
コメントを投稿