db/Plugin: use std::unique_ptr<> to manage Database pointers

This commit is contained in:
Max Kellermann 2019-02-20 20:32:11 +01:00
parent 2125e3ed57
commit 6c28adbcd2
15 changed files with 93 additions and 73 deletions

View File

@ -188,7 +188,7 @@ glue_db_init_and_load(const ConfigData &config)
instance->database = instance->database =
CreateConfiguredDatabase(config, instance->event_loop, CreateConfiguredDatabase(config, instance->event_loop,
instance->io_thread.GetEventLoop(), instance->io_thread.GetEventLoop(),
*instance); *instance).release();
if (instance->database == nullptr) if (instance->database == nullptr)
return true; return true;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2003-2018 The Music Player Daemon Project * Copyright 2003-2019 The Music Player Daemon Project
* http://www.musicpd.org * http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
@ -19,6 +19,7 @@
#include "Configured.hxx" #include "Configured.hxx"
#include "DatabaseGlue.hxx" #include "DatabaseGlue.hxx"
#include "Interface.hxx"
#include "config/Data.hxx" #include "config/Data.hxx"
#include "config/Param.hxx" #include "config/Param.hxx"
#include "config/Block.hxx" #include "config/Block.hxx"
@ -26,7 +27,7 @@
#include "fs/StandardDirectory.hxx" #include "fs/StandardDirectory.hxx"
#include "util/RuntimeError.hxx" #include "util/RuntimeError.hxx"
Database * DatabasePtr
CreateConfiguredDatabase(const ConfigData &config, CreateConfiguredDatabase(const ConfigData &config,
EventLoop &main_event_loop, EventLoop &io_event_loop, EventLoop &main_event_loop, EventLoop &io_event_loop,
DatabaseListener &listener) DatabaseListener &listener)

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2003-2018 The Music Player Daemon Project * Copyright 2003-2019 The Music Player Daemon Project
* http://www.musicpd.org * http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
@ -20,10 +20,11 @@
#ifndef MPD_DB_CONFIG_HXX #ifndef MPD_DB_CONFIG_HXX
#define MPD_DB_CONFIG_HXX #define MPD_DB_CONFIG_HXX
#include "Ptr.hxx"
struct ConfigData; struct ConfigData;
class EventLoop; class EventLoop;
class DatabaseListener; class DatabaseListener;
class Database;
/** /**
* Read database configuration settings and create a #Database * Read database configuration settings and create a #Database
@ -32,7 +33,7 @@ class Database;
* *
* Throws #std::runtime_error on error. * Throws #std::runtime_error on error.
*/ */
Database * DatabasePtr
CreateConfiguredDatabase(const ConfigData &config, CreateConfiguredDatabase(const ConfigData &config,
EventLoop &main_event_loop, EventLoop &io_event_loop, EventLoop &main_event_loop, EventLoop &io_event_loop,
DatabaseListener &listener); DatabaseListener &listener);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2003-2018 The Music Player Daemon Project * Copyright 2003-2019 The Music Player Daemon Project
* http://www.musicpd.org * http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
@ -18,13 +18,14 @@
*/ */
#include "DatabaseGlue.hxx" #include "DatabaseGlue.hxx"
#include "Interface.hxx"
#include "Registry.hxx" #include "Registry.hxx"
#include "DatabaseError.hxx" #include "DatabaseError.hxx"
#include "util/RuntimeError.hxx" #include "util/RuntimeError.hxx"
#include "config/Block.hxx" #include "config/Block.hxx"
#include "DatabasePlugin.hxx" #include "DatabasePlugin.hxx"
Database * DatabasePtr
DatabaseGlobalInit(EventLoop &main_event_loop, DatabaseGlobalInit(EventLoop &main_event_loop,
EventLoop &io_event_loop, EventLoop &io_event_loop,
DatabaseListener &listener, DatabaseListener &listener,

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2003-2018 The Music Player Daemon Project * Copyright 2003-2019 The Music Player Daemon Project
* http://www.musicpd.org * http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
@ -20,12 +20,11 @@
#ifndef MPD_DATABASE_GLUE_HXX #ifndef MPD_DATABASE_GLUE_HXX
#define MPD_DATABASE_GLUE_HXX #define MPD_DATABASE_GLUE_HXX
#include "util/Compiler.h" #include "Ptr.hxx"
struct ConfigBlock; struct ConfigBlock;
class EventLoop; class EventLoop;
class DatabaseListener; class DatabaseListener;
class Database;
/** /**
* Initialize the database library. * Initialize the database library.
@ -34,7 +33,7 @@ class Database;
* *
* @param block the database configuration block * @param block the database configuration block
*/ */
Database * DatabasePtr
DatabaseGlobalInit(EventLoop &main_event_loop, DatabaseGlobalInit(EventLoop &main_event_loop,
EventLoop &io_event_loop, EventLoop &io_event_loop,
DatabaseListener &listener, DatabaseListener &listener,

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2003-2018 The Music Player Daemon Project * Copyright 2003-2019 The Music Player Daemon Project
* http://www.musicpd.org * http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
@ -26,10 +26,11 @@
#ifndef MPD_DATABASE_PLUGIN_HXX #ifndef MPD_DATABASE_PLUGIN_HXX
#define MPD_DATABASE_PLUGIN_HXX #define MPD_DATABASE_PLUGIN_HXX
#include "Ptr.hxx"
struct ConfigBlock; struct ConfigBlock;
class EventLoop; class EventLoop;
class DatabaseListener; class DatabaseListener;
class Database;
struct DatabasePlugin { struct DatabasePlugin {
/** /**
@ -52,10 +53,10 @@ struct DatabasePlugin {
* @param io_event_loop the #EventLoop running on the * @param io_event_loop the #EventLoop running on the
* #EventThread, i.e. the one used for background I/O * #EventThread, i.e. the one used for background I/O
*/ */
Database *(*create)(EventLoop &main_event_loop, DatabasePtr (*create)(EventLoop &main_event_loop,
EventLoop &io_event_loop, EventLoop &io_event_loop,
DatabaseListener &listener, DatabaseListener &listener,
const ConfigBlock &block); const ConfigBlock &block);
constexpr bool RequireStorage() const { constexpr bool RequireStorage() const {
return flags & FLAG_REQUIRE_STORAGE; return flags & FLAG_REQUIRE_STORAGE;

29
src/db/Ptr.hxx Normal file
View File

@ -0,0 +1,29 @@
/*
* Copyright 2003-2019 The Music Player Daemon Project
* http://www.musicpd.org
*
* 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
* (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.
*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef MPD_DATABASE_PTR_HXX
#define MPD_DATABASE_PTR_HXX
#include <memory>
class Database;
typedef std::unique_ptr<Database> DatabasePtr;
#endif

View File

@ -112,10 +112,10 @@ public:
ProxyDatabase(EventLoop &_loop, DatabaseListener &_listener, ProxyDatabase(EventLoop &_loop, DatabaseListener &_listener,
const ConfigBlock &block); const ConfigBlock &block);
static Database *Create(EventLoop &main_event_loop, static DatabasePtr Create(EventLoop &main_event_loop,
EventLoop &io_event_loop, EventLoop &io_event_loop,
DatabaseListener &listener, DatabaseListener &listener,
const ConfigBlock &block); const ConfigBlock &block);
void Open() override; void Open() override;
void Close() noexcept override; void Close() noexcept override;
@ -440,12 +440,12 @@ ProxyDatabase::ProxyDatabase(EventLoop &_loop, DatabaseListener &_listener,
{ {
} }
Database * DatabasePtr
ProxyDatabase::Create(EventLoop &loop, EventLoop &, ProxyDatabase::Create(EventLoop &loop, EventLoop &,
DatabaseListener &listener, DatabaseListener &listener,
const ConfigBlock &block) const ConfigBlock &block)
{ {
return new ProxyDatabase(loop, listener, block); return std::make_unique<ProxyDatabase>(loop, listener, block);
} }
void void

View File

@ -45,8 +45,6 @@ Directory::Directory(std::string &&_path_utf8, Directory *_parent) noexcept
Directory::~Directory() noexcept Directory::~Directory() noexcept
{ {
delete mounted_database;
songs.clear_and_dispose(Song::Disposer()); songs.clear_and_dispose(Song::Disposer());
children.clear_and_dispose(DeleteDisposer()); children.clear_and_dispose(DeleteDisposer());
} }

View File

@ -23,6 +23,7 @@
#include "util/Compiler.h" #include "util/Compiler.h"
#include "db/Visitor.hxx" #include "db/Visitor.hxx"
#include "db/PlaylistVector.hxx" #include "db/PlaylistVector.hxx"
#include "db/Ptr.hxx"
#include "Song.hxx" #include "Song.hxx"
#include <boost/intrusive/list.hpp> #include <boost/intrusive/list.hpp>
@ -43,7 +44,6 @@ static constexpr unsigned DEVICE_INARCHIVE = -1;
static constexpr unsigned DEVICE_CONTAINER = -2; static constexpr unsigned DEVICE_CONTAINER = -2;
class SongFilter; class SongFilter;
class Database;
struct Directory { struct Directory {
static constexpr auto link_mode = boost::intrusive::normal_link; static constexpr auto link_mode = boost::intrusive::normal_link;
@ -96,7 +96,7 @@ struct Directory {
* If this is not nullptr, then this directory does not really * If this is not nullptr, then this directory does not really
* exist, but is a mount point for another #Database. * exist, but is a mount point for another #Database.
*/ */
Database *mounted_database = nullptr; DatabasePtr mounted_database;
public: public:
Directory(std::string &&_path_utf8, Directory *_parent) noexcept; Directory(std::string &&_path_utf8, Directory *_parent) noexcept;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2003-2018 The Music Player Daemon Project * Copyright 2003-2019 The Music Player Daemon Project
* http://www.musicpd.org * http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
@ -84,12 +84,12 @@ inline SimpleDatabase::SimpleDatabase(AllocatedPath &&_path,
prefixed_light_song(nullptr) { prefixed_light_song(nullptr) {
} }
Database * DatabasePtr
SimpleDatabase::Create(EventLoop &, EventLoop &, SimpleDatabase::Create(EventLoop &, EventLoop &,
gcc_unused DatabaseListener &listener, gcc_unused DatabaseListener &listener,
const ConfigBlock &block) const ConfigBlock &block)
{ {
return new SimpleDatabase(block); return std::make_unique<SimpleDatabase>(block);
} }
void void
@ -390,13 +390,13 @@ SimpleDatabase::Save()
} }
void void
SimpleDatabase::Mount(const char *uri, Database *db) SimpleDatabase::Mount(const char *uri, DatabasePtr db)
{ {
#if !CLANG_CHECK_VERSION(3,6) #if !CLANG_CHECK_VERSION(3,6)
/* disabled on clang due to -Wtautological-pointer-compare */ /* disabled on clang due to -Wtautological-pointer-compare */
assert(uri != nullptr); assert(uri != nullptr);
assert(db != nullptr);
#endif #endif
assert(db != nullptr);
assert(*uri != 0); assert(*uri != 0);
ScopeDatabaseLock protect; ScopeDatabaseLock protect;
@ -411,7 +411,7 @@ SimpleDatabase::Mount(const char *uri, Database *db)
"Parent not found"); "Parent not found");
Directory *mnt = r.directory->CreateChild(r.uri); Directory *mnt = r.directory->CreateChild(r.uri);
mnt->mounted_database = db; mnt->mounted_database = std::move(db);
} }
static constexpr bool static constexpr bool
@ -441,27 +441,21 @@ SimpleDatabase::Mount(const char *local_uri, const char *storage_uri)
#ifndef ENABLE_ZLIB #ifndef ENABLE_ZLIB
constexpr bool compress = false; constexpr bool compress = false;
#endif #endif
auto db = new SimpleDatabase(cache_path / name_fs, auto db = std::make_unique<SimpleDatabase>(cache_path / name_fs,
compress); compress);
try { db->Open();
db->Open();
} catch (...) {
delete db;
throw;
}
// TODO: update the new database instance? // TODO: update the new database instance?
try { try {
Mount(local_uri, db); Mount(local_uri, std::move(db));
} catch (...) { } catch (...) {
db->Close(); db->Close();
delete db;
throw; throw;
} }
} }
inline Database * inline DatabasePtr
SimpleDatabase::LockUmountSteal(const char *uri) noexcept SimpleDatabase::LockUmountSteal(const char *uri) noexcept
{ {
ScopeDatabaseLock protect; ScopeDatabaseLock protect;
@ -470,8 +464,7 @@ SimpleDatabase::LockUmountSteal(const char *uri) noexcept
if (r.uri != nullptr || !r.directory->IsMount()) if (r.uri != nullptr || !r.directory->IsMount())
return nullptr; return nullptr;
Database *db = r.directory->mounted_database; auto db = std::move(r.directory->mounted_database);
r.directory->mounted_database = nullptr;
r.directory->Delete(); r.directory->Delete();
return db; return db;
@ -480,12 +473,11 @@ SimpleDatabase::LockUmountSteal(const char *uri) noexcept
bool bool
SimpleDatabase::Unmount(const char *uri) noexcept SimpleDatabase::Unmount(const char *uri) noexcept
{ {
Database *db = LockUmountSteal(uri); auto db = LockUmountSteal(uri);
if (db == nullptr) if (db == nullptr)
return false; return false;
db->Close(); db->Close();
delete db;
return true; return true;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2003-2018 The Music Player Daemon Project * Copyright 2003-2019 The Music Player Daemon Project
* http://www.musicpd.org * http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
@ -21,6 +21,7 @@
#define MPD_SIMPLE_DATABASE_PLUGIN_HXX #define MPD_SIMPLE_DATABASE_PLUGIN_HXX
#include "db/Interface.hxx" #include "db/Interface.hxx"
#include "db/Ptr.hxx"
#include "fs/AllocatedPath.hxx" #include "fs/AllocatedPath.hxx"
#include "song/LightSong.hxx" #include "song/LightSong.hxx"
#include "util/Manual.hxx" #include "util/Manual.hxx"
@ -68,15 +69,14 @@ class SimpleDatabase : public Database {
mutable unsigned borrowed_song_count; mutable unsigned borrowed_song_count;
#endif #endif
public:
SimpleDatabase(const ConfigBlock &block); SimpleDatabase(const ConfigBlock &block);
SimpleDatabase(AllocatedPath &&_path, bool _compress) noexcept; SimpleDatabase(AllocatedPath &&_path, bool _compress) noexcept;
public: static DatabasePtr Create(EventLoop &main_event_loop,
static Database *Create(EventLoop &main_event_loop, EventLoop &io_event_loop,
EventLoop &io_event_loop, DatabaseListener &listener,
DatabaseListener &listener, const ConfigBlock &block);
const ConfigBlock &block);
gcc_pure gcc_pure
Directory &GetRoot() noexcept { Directory &GetRoot() noexcept {
@ -99,7 +99,7 @@ public:
* success, this object gains ownership of the given #Database * success, this object gains ownership of the given #Database
*/ */
gcc_nonnull_all gcc_nonnull_all
void Mount(const char *uri, Database *db); void Mount(const char *uri, DatabasePtr db);
/** /**
* Throws #std::runtime_error on error. * Throws #std::runtime_error on error.
@ -142,7 +142,7 @@ private:
*/ */
void Load(); void Load();
Database *LockUmountSteal(const char *uri) noexcept; DatabasePtr LockUmountSteal(const char *uri) noexcept;
}; };
extern const DatabasePlugin simple_db_plugin; extern const DatabasePlugin simple_db_plugin;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2003-2018 The Music Player Daemon Project * Copyright 2003-2019 The Music Player Daemon Project
* http://www.musicpd.org * http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
@ -82,10 +82,10 @@ public:
:Database(upnp_db_plugin), :Database(upnp_db_plugin),
event_loop(_event_loop) {} event_loop(_event_loop) {}
static Database *Create(EventLoop &main_event_loop, static DatabasePtr Create(EventLoop &main_event_loop,
EventLoop &io_event_loop, EventLoop &io_event_loop,
DatabaseListener &listener, DatabaseListener &listener,
const ConfigBlock &block) noexcept; const ConfigBlock &block) noexcept;
void Open() override; void Open() override;
void Close() noexcept override; void Close() noexcept override;
@ -146,12 +146,12 @@ private:
const UPnPDirObject& dirent) const; const UPnPDirObject& dirent) const;
}; };
Database * DatabasePtr
UpnpDatabase::Create(EventLoop &, EventLoop &io_event_loop, UpnpDatabase::Create(EventLoop &, EventLoop &io_event_loop,
gcc_unused DatabaseListener &listener, gcc_unused DatabaseListener &listener,
const ConfigBlock &) noexcept const ConfigBlock &) noexcept
{ {
return new UpnpDatabase(io_event_loop); return std::make_unique<UpnpDatabase>(io_event_loop);
} }
void void

View File

@ -94,7 +94,7 @@ UpdateService::CancelMount(const char *uri)
cancel_current = next.IsDefined() && next.storage == storage2; cancel_current = next.IsDefined() && next.storage == storage2;
} }
if (auto *db2 = dynamic_cast<SimpleDatabase *>(lr.directory->mounted_database)) { if (auto *db2 = dynamic_cast<SimpleDatabase *>(lr.directory->mounted_database.get())) {
queue.Erase(*db2); queue.Erase(*db2);
cancel_current |= next.IsDefined() && next.db == db2; cancel_current |= next.IsDefined() && next.db == db2;
} }
@ -188,7 +188,7 @@ UpdateService::Enqueue(const char *path, bool discard)
/* follow the mountpoint, update the mounted /* follow the mountpoint, update the mounted
database */ database */
db2 = dynamic_cast<SimpleDatabase *>(lr.directory->mounted_database); db2 = dynamic_cast<SimpleDatabase *>(lr.directory->mounted_database.get());
if (db2 == nullptr) if (db2 == nullptr)
throw std::runtime_error("Cannot update this type of database"); throw std::runtime_error("Cannot update this type of database");

View File

@ -133,15 +133,13 @@ try {
if (path != nullptr) if (path != nullptr)
block.AddBlockParam("path", path->value, path->line); block.AddBlockParam("path", path->value, path->line);
Database *db = plugin->create(init.GetEventLoop(), auto db = plugin->create(init.GetEventLoop(),
init.GetEventLoop(), init.GetEventLoop(),
database_listener, block); database_listener, block);
AtScopeExit(db) { delete db; };
db->Open(); db->Open();
AtScopeExit(db) { db->Close(); }; AtScopeExit(&db) { db->Close(); };
const DatabaseSelection selection("", true); const DatabaseSelection selection("", true);