Commit cf6281a5 authored by Max Kellermann's avatar Max Kellermann

Instance: add Database attribute

Move from db/DatabaseGlue.cxx, eliminating global variable.
parent f00710a5
......@@ -205,7 +205,6 @@ src_mpd_SOURCES += \
src/db/Uri.hxx \
src/db/Directory.cxx src/db/Directory.hxx \
src/db/DirectorySave.cxx src/db/DirectorySave.hxx \
src/db/DatabaseSimple.hxx \
src/db/DatabaseGlue.cxx src/db/DatabaseGlue.hxx \
src/db/DatabaseSong.cxx src/db/DatabaseSong.hxx \
src/db/DatabasePrint.cxx src/db/DatabasePrint.hxx \
......
......@@ -22,10 +22,18 @@
#include "Partition.hxx"
#include "Idle.hxx"
#include "Stats.hxx"
#include "db/DatabaseGlue.hxx"
#include "db/DatabaseError.hxx"
#ifdef ENABLE_DATABASE
Database *
Instance::GetDatabase(Error &error)
{
if (database == nullptr)
error.Set(db_domain, DB_DISABLED, "No database");
return database;
}
void
Instance::DeleteSong(const char *uri)
{
......@@ -35,8 +43,10 @@ Instance::DeleteSong(const char *uri)
void
Instance::DatabaseModified()
{
assert(database != nullptr);
stats_invalidate();
partition->DatabaseModified(*GetDatabase());
partition->DatabaseModified(*database);
idle_add(IDLE_DATABASE);
}
......
......@@ -30,9 +30,11 @@ class NeighborGlue;
#ifdef ENABLE_DATABASE
#include "db/DatabaseListener.hxx"
class Database;
class UpdateService;
#endif
class Error;
class ClientList;
struct Partition;
......@@ -55,6 +57,8 @@ struct Instance final
#endif
#ifdef ENABLE_DATABASE
Database *database;
UpdateService *update;
#endif
......@@ -69,6 +73,12 @@ struct Instance final
}
#ifdef ENABLE_DATABASE
/**
* Returns the global #Database instance. May return nullptr
* if this MPD configuration has no database (no
* music_directory was configured).
*/
Database *GetDatabase(Error &error);
void DeleteSong(const char *uri);
......
......@@ -195,22 +195,26 @@ glue_db_init_and_load(void)
if (param == nullptr)
return true;
bool is_simple;
Error error;
if (!DatabaseGlobalInit(*main_loop, *instance, *param, error))
instance->database = DatabaseGlobalInit(*main_loop, *instance, *param,
is_simple, error);
if (instance->database == nullptr)
FatalError(error);
delete allocated;
if (!DatabaseGlobalOpen(error))
if (!instance->database->Open(error))
FatalError(error);
if (!db_is_simple())
if (!is_simple)
return true;
instance->update = new UpdateService(*main_loop, db_get_simple());
SimpleDatabase &db = *(SimpleDatabase *)instance->database;
instance->update = new UpdateService(*main_loop, db);
/* run database update after daemonization? */
return db_exists();
return db.FileExists();
}
#endif
......@@ -577,8 +581,8 @@ int mpd_main(int argc, char *argv[])
#ifdef ENABLE_DATABASE
delete instance->update;
DatabaseGlobalDeinit();
instance->database->Close();
delete instance->database;
#endif
#ifdef ENABLE_SQLITE
......
......@@ -23,7 +23,8 @@
#include "Playlist.hxx"
#include "queue/QueuePrint.hxx"
#include "SongPrint.hxx"
#include "db/DatabaseGlue.hxx"
#include "Partition.hxx"
#include "Instance.hxx"
#include "db/DatabasePlugin.hxx"
#include "client/Client.hxx"
#include "input/InputStream.hxx"
......@@ -115,7 +116,7 @@ playlist_print_changes_position(Client &client,
static bool
PrintSongDetails(Client &client, const char *uri_utf8)
{
const Database *db = GetDatabase();
const Database *db = client.partition.instance.database;
if (db == nullptr)
return false;
......
......@@ -33,6 +33,13 @@
#include <assert.h>
#include <string.h>
#ifdef ENABLE_DATABASE
SongLoader::SongLoader(const Client &_client)
:client(&_client), db(_client.GetDatabase(IgnoreError())) {}
#endif
DetachedSong *
SongLoader::LoadFile(const char *path_utf8, Error &error) const
{
......
......@@ -45,19 +45,16 @@ class SongLoader {
public:
#ifdef ENABLE_DATABASE
SongLoader(const Client *_client, const Database *_db=nullptr)
:client(_client), db(_db) {}
explicit SongLoader(const Client &_client)
:client(&_client), db(nullptr) {}
explicit SongLoader(const Client &_client);
explicit SongLoader(const Database *_db)
:client(nullptr), db(_db) {}
explicit SongLoader(std::nullptr_t)
:client(nullptr), db(nullptr) {}
explicit SongLoader(const Client &_client, const Database *_db)
:client(&_client), db(_db) {}
#else
explicit SongLoader(const Client &_client)
:client(&_client) {}
explicit SongLoader(const Client *_client)
:client(_client) {}
explicit SongLoader(std::nullptr_t)
:client(nullptr) {}
#endif
gcc_nonnull_all
......
......@@ -23,9 +23,9 @@
#include "PlaylistState.hxx"
#include "fs/TextFile.hxx"
#include "Partition.hxx"
#include "Instance.hxx"
#include "mixer/Volume.hxx"
#include "SongLoader.hxx"
#include "db/DatabaseGlue.hxx"
#include "fs/FileSystem.hxx"
#include "util/Domain.hxx"
#include "Log.hxx"
......@@ -98,7 +98,11 @@ StateFile::Read()
return;
}
const SongLoader song_loader(nullptr, GetDatabase());
#ifdef ENABLE_DATABASE
const SongLoader song_loader(partition.instance.database);
#else
const SongLoader song_loader(nullptr);
#endif
const char *line;
while ((line = file.ReadLine()) != NULL) {
......
......@@ -21,8 +21,9 @@
#include "Stats.hxx"
#include "PlayerControl.hxx"
#include "client/Client.hxx"
#include "Partition.hxx"
#include "Instance.hxx"
#include "db/Selection.hxx"
#include "db/DatabaseGlue.hxx"
#include "db/DatabasePlugin.hxx"
#include "util/Error.hxx"
#include "system/Clock.hxx"
......@@ -60,8 +61,6 @@ void stats_global_init(void)
void
stats_invalidate()
{
assert(GetDatabase() != nullptr);
stats_validity = StatsValidity::INVALID;
}
......@@ -132,7 +131,7 @@ stats_print(Client &client)
(unsigned long)(client.player_control.GetTotalPlayTime() + 0.5));
#ifdef ENABLE_DATABASE
const Database *db = GetDatabase();
const Database *db = client.partition.instance.database;
if (db != nullptr)
db_stats_print(client, *db);
#endif
......
......@@ -20,5 +20,17 @@
#include "config.h"
#include "ClientInternal.hxx"
#include "util/Domain.hxx"
#include "Partition.hxx"
#include "Instance.hxx"
const Domain client_domain("client");
#ifdef ENABLE_DATABASE
const Database *
Client::GetDatabase(Error &error) const
{
return partition.instance.GetDatabase(error);
}
#endif
......@@ -38,6 +38,7 @@ struct sockaddr;
class EventLoop;
class Path;
struct Partition;
class Database;
class Client final : private FullyBufferedSocket, TimeoutMonitor {
public:
......@@ -169,6 +170,11 @@ public:
*/
bool AllowFile(Path path_fs, Error &error) const;
/**
* Wrapper for Instance::GetDatabase().
*/
const Database *GetDatabase(Error &error) const;
private:
/* virtual methods from class BufferedSocket */
virtual InputResult OnSocketInput(void *data, size_t length) override;
......
......@@ -120,7 +120,7 @@ handle_searchaddpl(Client &client, int argc, char *argv[])
}
Error error;
const Database *db = GetDatabase(error);
const Database *db = client.GetDatabase(error);
if (db == nullptr)
return print_error(client, error);
......
......@@ -19,7 +19,6 @@
#include "config.h"
#include "PlaylistCommands.hxx"
#include "db/DatabaseGlue.hxx"
#include "db/DatabasePlaylist.hxx"
#include "CommandError.hxx"
#include "PlaylistPrint.hxx"
......@@ -193,7 +192,7 @@ handle_playlistadd(Client &client, gcc_unused int argc, char *argv[])
success = spl_append_uri(playlist, loader, uri, error);
} else {
#ifdef ENABLE_DATABASE
const Database *db = GetDatabase(error);
const Database *db = client.GetDatabase(error);
if (db == nullptr)
return print_error(client, error);
......
......@@ -28,6 +28,9 @@
#include "sticker/StickerDatabase.hxx"
#include "CommandError.hxx"
#include "protocol/Result.hxx"
#include "client/Client.hxx"
#include "Partition.hxx"
#include "Instance.hxx"
#include "util/Error.hxx"
#include <string.h>
......@@ -52,7 +55,7 @@ static CommandResult
handle_sticker_song(Client &client, int argc, char *argv[])
{
Error error;
const Database *db = GetDatabase(error);
const Database *db = client.GetDatabase(error);
if (db == nullptr)
return print_error(client, error);
......
......@@ -19,30 +19,18 @@
#include "config.h"
#include "DatabaseGlue.hxx"
#include "DatabaseSimple.hxx"
#include "Registry.hxx"
#include "DatabaseError.hxx"
#include "Directory.hxx"
#include "util/Error.hxx"
#include "config/ConfigData.hxx"
#include "Stats.hxx"
#include "DatabasePlugin.hxx"
#include "plugins/SimpleDatabasePlugin.hxx"
#include <assert.h>
#include <string.h>
static Database *db;
static bool db_is_open;
static bool is_simple;
bool
Database *
DatabaseGlobalInit(EventLoop &loop, DatabaseListener &listener,
const config_param &param, Error &error)
const config_param &param, bool &is_simple, Error &error)
{
assert(db == nullptr);
assert(!db_is_open);
const char *plugin_name =
param.GetBlockValue("plugin", "simple");
is_simple = strcmp(plugin_name, "simple") == 0;
......@@ -51,79 +39,8 @@ DatabaseGlobalInit(EventLoop &loop, DatabaseListener &listener,
if (plugin == nullptr) {
error.Format(db_domain,
"No such database plugin: %s", plugin_name);
return false;
return nullptr;
}
db = plugin->create(loop, listener, param, error);
return db != nullptr;
}
void
DatabaseGlobalDeinit(void)
{
if (db_is_open)
db->Close();
if (db != nullptr)
delete db;
}
const Database *
GetDatabase()
{
assert(db == nullptr || db_is_open);
return db;
}
const Database *
GetDatabase(Error &error)
{
assert(db == nullptr || db_is_open);
if (db == nullptr)
error.Set(db_domain, DB_DISABLED, "No database");
return db;
}
bool
db_is_simple(void)
{
assert(db == nullptr || db_is_open);
return is_simple;
}
SimpleDatabase &
db_get_simple()
{
assert(is_simple);
assert(db != nullptr);
return *(SimpleDatabase *)db;
}
bool
DatabaseGlobalOpen(Error &error)
{
assert(db != nullptr);
assert(!db_is_open);
if (!db->Open(error))
return false;
db_is_open = true;
return true;
}
bool
db_exists()
{
assert(db != nullptr);
assert(db_is_open);
assert(db_is_simple());
return ((SimpleDatabase *)db)->GetUpdateStamp() > 0;
return plugin->create(loop, listener, param, error);
}
......@@ -32,31 +32,11 @@ class Error;
* Initialize the database library.
*
* @param param the database configuration block
* @param is_simple returns whether this is the "simple" database
* plugin
*/
bool
Database *
DatabaseGlobalInit(EventLoop &loop, DatabaseListener &listener,
const config_param &param, Error &error);
void
DatabaseGlobalDeinit(void);
bool
DatabaseGlobalOpen(Error &error);
/**
* Returns the global #Database instance. May return nullptr if this MPD
* configuration has no database (no music_directory was configured).
*/
gcc_const
const Database *
GetDatabase();
/**
* Returns the global #Database instance. May return nullptr if this MPD
* configuration has no database (no music_directory was configured).
*/
gcc_pure
const Database *
GetDatabase(Error &error);
const config_param &param, bool &is_simple, Error &error);
#endif
......@@ -28,7 +28,6 @@
#include "LightSong.hxx"
#include "LightDirectory.hxx"
#include "PlaylistInfo.hxx"
#include "DatabaseGlue.hxx"
#include "DatabasePlugin.hxx"
#include <functional>
......@@ -129,7 +128,7 @@ bool
db_selection_print(Client &client, const DatabaseSelection &selection,
bool full, Error &error)
{
const Database *db = GetDatabase(error);
const Database *db = client.GetDatabase(error);
if (db == nullptr)
return false;
......@@ -173,7 +172,7 @@ searchStatsForSongsIn(Client &client, const char *name,
const SongFilter *filter,
Error &error)
{
const Database *db = GetDatabase(error);
const Database *db = client.GetDatabase(error);
if (db == nullptr)
return false;
......@@ -229,7 +228,7 @@ listAllUniqueTags(Client &client, int type,
const SongFilter *filter,
Error &error)
{
const Database *db = GetDatabase(error);
const Database *db = client.GetDatabase(error);
if (db == nullptr)
return false;
......
......@@ -22,6 +22,7 @@
#include "DatabaseGlue.hxx"
#include "DatabasePlugin.hxx"
#include "Partition.hxx"
#include "Instance.hxx"
#include "util/Error.hxx"
#include "DetachedSong.hxx"
#include "Mapper.hxx"
......@@ -47,7 +48,7 @@ bool
AddFromDatabase(Partition &partition, const DatabaseSelection &selection,
Error &error)
{
const Database *db = GetDatabase(error);
const Database *db = partition.instance.GetDatabase(error);
if (db == nullptr)
return false;
......
......@@ -35,10 +35,6 @@ class Error;
bool
db_is_simple(void);
gcc_pure
SimpleDatabase &
db_get_simple();
/**
* Returns true if there is a valid database file on the disk.
*
......
......@@ -59,6 +59,9 @@ public:
bool Save(Error &error);
/**
* Returns true if there is a valid database file on the disk.
*/
bool FileExists() const {
return mtime > 0;
}
......
......@@ -137,6 +137,12 @@ DetachedSong::Update()
return false;
}
const Database *
Client::GetDatabase(gcc_unused Error &error) const
{
return reinterpret_cast<const Database *>(this);
}
bool
Client::AllowFile(gcc_unused Path path_fs, gcc_unused Error &error) const
{
......@@ -220,7 +226,7 @@ class TranslateSongTest : public CppUnit::TestFixture {
void TestInsecure() {
/* illegal because secure=false */
DetachedSong song1 (uri1);
const SongLoader loader(reinterpret_cast<const Client *>(1));
const SongLoader loader(*reinterpret_cast<const Client *>(1));
CPPUNIT_ASSERT(!playlist_check_translate_song(song1, nullptr,
loader));
}
......@@ -261,7 +267,8 @@ class TranslateSongTest : public CppUnit::TestFixture {
void TestRelative() {
const Database &db = *reinterpret_cast<const Database *>(1);
const SongLoader secure_loader(&db);
const SongLoader insecure_loader(reinterpret_cast<const Client *>(1), &db);
const SongLoader insecure_loader(*reinterpret_cast<const Client *>(1),
&db);
/* map to music_directory */
DetachedSong song1("bar.ogg", MakeTag2b());
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment