db/Interface: GetSong() throws exception on error

This commit is contained in:
Max Kellermann 2016-03-19 00:13:57 +01:00
parent 7ad7caa2ae
commit 2fd5182608
15 changed files with 43 additions and 67 deletions

View File

@ -127,9 +127,7 @@ PrintSongDetails(Response &r, Partition &partition, const char *uri_utf8)
const LightSong *song; const LightSong *song;
try { try {
song = db->GetSong(uri_utf8, IgnoreError()); song = db->GetSong(uri_utf8);
if (song == nullptr)
return false;
} catch (const std::runtime_error &e) { } catch (const std::runtime_error &e) {
return false; return false;
} }

View File

@ -38,21 +38,20 @@ SongLoader::SongLoader(const Client &_client)
#endif #endif
DetachedSong * DetachedSong *
SongLoader::LoadFromDatabase(const char *uri, Error &error) const SongLoader::LoadFromDatabase(const char *uri) const
{ {
#ifdef ENABLE_DATABASE #ifdef ENABLE_DATABASE
if (db != nullptr) if (db != nullptr)
return DatabaseDetachSong(*db, *storage, uri, error); return DatabaseDetachSong(*db, *storage, uri);
#else #else
(void)uri; (void)uri;
(void)error;
#endif #endif
throw PlaylistError(PlaylistResult::NO_SUCH_SONG, "No database"); throw PlaylistError(PlaylistResult::NO_SUCH_SONG, "No database");
} }
DetachedSong * DetachedSong *
SongLoader::LoadFile(const char *path_utf8, Path path_fs, Error &error) const SongLoader::LoadFile(const char *path_utf8, Path path_fs) const
{ {
#ifdef ENABLE_DATABASE #ifdef ENABLE_DATABASE
if (storage != nullptr) { if (storage != nullptr) {
@ -60,10 +59,8 @@ SongLoader::LoadFile(const char *path_utf8, Path path_fs, Error &error) const
if (suffix != nullptr) if (suffix != nullptr)
/* this path was relative to the music /* this path was relative to the music
directory - obtain it from the database */ directory - obtain it from the database */
return LoadFromDatabase(suffix, error); return LoadFromDatabase(suffix);
} }
#else
(void)error;
#endif #endif
DetachedSong song(path_utf8); DetachedSong song(path_utf8);
@ -74,7 +71,7 @@ SongLoader::LoadFile(const char *path_utf8, Path path_fs, Error &error) const
} }
DetachedSong * DetachedSong *
SongLoader::LoadSong(const LocatedUri &located_uri, Error &error) const SongLoader::LoadSong(const LocatedUri &located_uri) const
{ {
switch (located_uri.type) { switch (located_uri.type) {
case LocatedUri::Type::UNKNOWN: case LocatedUri::Type::UNKNOWN:
@ -84,11 +81,10 @@ SongLoader::LoadSong(const LocatedUri &located_uri, Error &error) const
return new DetachedSong(located_uri.canonical_uri); return new DetachedSong(located_uri.canonical_uri);
case LocatedUri::Type::RELATIVE: case LocatedUri::Type::RELATIVE:
return LoadFromDatabase(located_uri.canonical_uri, error); return LoadFromDatabase(located_uri.canonical_uri);
case LocatedUri::Type::PATH: case LocatedUri::Type::PATH:
return LoadFile(located_uri.canonical_uri, located_uri.path, return LoadFile(located_uri.canonical_uri, located_uri.path);
error);
} }
gcc_unreachable(); gcc_unreachable();
@ -110,5 +106,5 @@ SongLoader::LoadSong(const char *uri_utf8, Error &error) const
if (located_uri.IsUnknown()) if (located_uri.IsUnknown())
return nullptr; return nullptr;
return LoadSong(located_uri, error); return LoadSong(located_uri);
} }

View File

@ -68,18 +68,17 @@ public:
} }
#endif #endif
DetachedSong *LoadSong(const LocatedUri &uri, Error &error) const; DetachedSong *LoadSong(const LocatedUri &uri) const;
gcc_nonnull_all gcc_nonnull_all
DetachedSong *LoadSong(const char *uri_utf8, Error &error) const; DetachedSong *LoadSong(const char *uri_utf8, Error &error) const;
private: private:
gcc_nonnull_all gcc_nonnull_all
DetachedSong *LoadFromDatabase(const char *uri, Error &error) const; DetachedSong *LoadFromDatabase(const char *uri) const;
gcc_nonnull_all gcc_nonnull_all
DetachedSong *LoadFile(const char *path_utf8, Path path_fs, DetachedSong *LoadFile(const char *path_utf8, Path path_fs) const;
Error &error) const;
}; };
#endif #endif

View File

@ -41,17 +41,14 @@
#include <memory> #include <memory>
#include <limits> #include <limits>
static CommandResult static void
AddUri(Client &client, const LocatedUri &uri, Response &r) AddUri(Client &client, const LocatedUri &uri)
{ {
Error error; std::unique_ptr<DetachedSong> song(SongLoader(client).LoadSong(uri));
std::unique_ptr<DetachedSong> song(SongLoader(client).LoadSong(uri, error)); assert(song);
if (song == nullptr)
return print_error(r, error);
auto &partition = client.partition; auto &partition = client.partition;
partition.playlist.AppendSong(partition.pc, std::move(*song)); partition.playlist.AppendSong(partition.pc, std::move(*song));
return CommandResult::OK;
} }
static CommandResult static CommandResult
@ -98,7 +95,8 @@ handle_add(Client &client, Request args, Response &r)
case LocatedUri::Type::ABSOLUTE: case LocatedUri::Type::ABSOLUTE:
case LocatedUri::Type::PATH: case LocatedUri::Type::PATH:
return AddUri(client, located_uri, r); AddUri(client, located_uri);
return CommandResult::OK;
case LocatedUri::Type::RELATIVE: case LocatedUri::Type::RELATIVE:
return AddDatabaseSelection(client, located_uri.canonical_uri, return AddDatabaseSelection(client, located_uri.canonical_uri,

View File

@ -62,9 +62,7 @@ handle_sticker_song(Response &r, Partition &partition, Request args)
/* get song song_id key */ /* get song song_id key */
if (args.size == 4 && StringIsEqual(cmd, "get")) { if (args.size == 4 && StringIsEqual(cmd, "get")) {
const LightSong *song = db->GetSong(args[2], error); const LightSong *song = db->GetSong(args[2]);
if (song == nullptr)
return print_error(r, error);
const auto value = sticker_song_get_value(*song, args[3], const auto value = sticker_song_get_value(*song, args[3],
error); error);
@ -82,9 +80,8 @@ handle_sticker_song(Response &r, Partition &partition, Request args)
return CommandResult::OK; return CommandResult::OK;
/* list song song_id */ /* list song song_id */
} else if (args.size == 3 && StringIsEqual(cmd, "list")) { } else if (args.size == 3 && StringIsEqual(cmd, "list")) {
const LightSong *song = db->GetSong(args[2], error); const LightSong *song = db->GetSong(args[2]);
if (song == nullptr) assert(song != nullptr);
return print_error(r, error);
Sticker *sticker = sticker_song_get(*song, error); Sticker *sticker = sticker_song_get(*song, error);
db->ReturnSong(song); db->ReturnSong(song);
@ -97,9 +94,8 @@ handle_sticker_song(Response &r, Partition &partition, Request args)
return CommandResult::OK; return CommandResult::OK;
/* set song song_id id key */ /* set song song_id id key */
} else if (args.size == 5 && StringIsEqual(cmd, "set")) { } else if (args.size == 5 && StringIsEqual(cmd, "set")) {
const LightSong *song = db->GetSong(args[2], error); const LightSong *song = db->GetSong(args[2]);
if (song == nullptr) assert(song != nullptr);
return print_error(r, error);
bool ret = sticker_song_set_value(*song, args[3], args[4], bool ret = sticker_song_set_value(*song, args[3], args[4],
error); error);
@ -117,9 +113,8 @@ handle_sticker_song(Response &r, Partition &partition, Request args)
/* delete song song_id [key] */ /* delete song song_id [key] */
} else if ((args.size == 3 || args.size == 4) && } else if ((args.size == 3 || args.size == 4) &&
StringIsEqual(cmd, "delete")) { StringIsEqual(cmd, "delete")) {
const LightSong *song = db->GetSong(args[2], error); const LightSong *song = db->GetSong(args[2]);
if (song == nullptr) assert(song != nullptr);
return print_error(r, error);
bool ret = args.size == 3 bool ret = args.size == 3
? sticker_song_delete(*song, error) ? sticker_song_delete(*song, error)

View File

@ -41,12 +41,10 @@ DatabaseDetachSong(const Storage &storage, const LightSong &song)
} }
DetachedSong * DetachedSong *
DatabaseDetachSong(const Database &db, const Storage &storage, const char *uri, DatabaseDetachSong(const Database &db, const Storage &storage, const char *uri)
Error &error)
{ {
const LightSong *tmp = db.GetSong(uri, error); const LightSong *tmp = db.GetSong(uri);
if (tmp == nullptr) assert(tmp != nullptr);
return nullptr;
DetachedSong *song = new DetachedSong(DatabaseDetachSong(storage, DetachedSong *song = new DetachedSong(DatabaseDetachSong(storage,
*tmp)); *tmp));

View File

@ -26,7 +26,6 @@ struct LightSong;
class Database; class Database;
class Storage; class Storage;
class DetachedSong; class DetachedSong;
class Error;
/** /**
* "Detach" the #Song object, i.e. convert it to a #DetachedSong * "Detach" the #Song object, i.e. convert it to a #DetachedSong
@ -44,7 +43,7 @@ DatabaseDetachSong(const Storage &storage, const LightSong &song);
*/ */
gcc_malloc gcc_nonnull_all gcc_malloc gcc_nonnull_all
DetachedSong * DetachedSong *
DatabaseDetachSong(const Database &db, const Storage &storage, const char *uri, DatabaseDetachSong(const Database &db, const Storage &storage,
Error &error); const char *uri);
#endif #endif

View File

@ -73,8 +73,7 @@ public:
* @param uri_utf8 the URI of the song within the music * @param uri_utf8 the URI of the song within the music
* directory (UTF-8) * directory (UTF-8)
*/ */
virtual const LightSong *GetSong(const char *uri_utf8, virtual const LightSong *GetSong(const char *uri_utf8) const = 0;
Error &error) const = 0;
/** /**
* Mark the song object as "unused". Call this on objects * Mark the song object as "unused". Call this on objects

View File

@ -115,8 +115,7 @@ public:
virtual void Open() override; virtual void Open() override;
virtual void Close() override; virtual void Close() override;
virtual const LightSong *GetSong(const char *uri_utf8, const LightSong *GetSong(const char *uri_utf8) const override;
Error &error) const override;
void ReturnSong(const LightSong *song) const override; void ReturnSong(const LightSong *song) const override;
virtual bool Visit(const DatabaseSelection &selection, virtual bool Visit(const DatabaseSelection &selection,
@ -519,7 +518,7 @@ ProxyDatabase::OnIdle()
} }
const LightSong * const LightSong *
ProxyDatabase::GetSong(const char *uri, gcc_unused Error &error) const ProxyDatabase::GetSong(const char *uri) const
{ {
// TODO: eliminate the const_cast // TODO: eliminate the const_cast
const_cast<ProxyDatabase *>(this)->EnsureConnected(); const_cast<ProxyDatabase *>(this)->EnsureConnected();

View File

@ -229,7 +229,7 @@ SimpleDatabase::Close()
} }
const LightSong * const LightSong *
SimpleDatabase::GetSong(const char *uri, Error &error) const SimpleDatabase::GetSong(const char *uri) const
{ {
assert(root != nullptr); assert(root != nullptr);
assert(prefixed_light_song == nullptr); assert(prefixed_light_song == nullptr);
@ -244,7 +244,7 @@ SimpleDatabase::GetSong(const char *uri, Error &error) const
protect.unlock(); protect.unlock();
const LightSong *song = const LightSong *song =
r.directory->mounted_database->GetSong(r.uri, error); r.directory->mounted_database->GetSong(r.uri);
if (song == nullptr) if (song == nullptr)
return nullptr; return nullptr;

View File

@ -110,8 +110,7 @@ public:
virtual void Open() override; virtual void Open() override;
virtual void Close() override; virtual void Close() override;
const LightSong *GetSong(const char *uri_utf8, const LightSong *GetSong(const char *uri_utf8) const override;
Error &error) const override;
void ReturnSong(const LightSong *song) const override; void ReturnSong(const LightSong *song) const override;
virtual bool Visit(const DatabaseSelection &selection, virtual bool Visit(const DatabaseSelection &selection,

View File

@ -82,8 +82,7 @@ public:
virtual void Open() override; virtual void Open() override;
virtual void Close() override; virtual void Close() override;
virtual const LightSong *GetSong(const char *uri_utf8, virtual const LightSong *GetSong(const char *uri_utf8) const override;
Error &error) const override;
void ReturnSong(const LightSong *song) const override; void ReturnSong(const LightSong *song) const override;
virtual bool Visit(const DatabaseSelection &selection, virtual bool Visit(const DatabaseSelection &selection,
@ -202,7 +201,7 @@ UpnpDatabase::ReturnSong(const LightSong *_song) const
// Get song info by path. We can receive either the id path, or the titles // Get song info by path. We can receive either the id path, or the titles
// one // one
const LightSong * const LightSong *
UpnpDatabase::GetSong(const char *uri, gcc_unused Error &error) const UpnpDatabase::GetSong(const char *uri) const
{ {
auto vpath = stringToTokens(uri, "/", true); auto vpath = stringToTokens(uri, "/", true);
if (vpath.size() < 2) if (vpath.size() < 2)

View File

@ -35,7 +35,7 @@ UpdatePlaylistSong(const Database &db, DetachedSong &song)
const LightSong *original; const LightSong *original;
try { try {
original = db.GetSong(song.GetURI(), IgnoreError()); original = db.GetSong(song.GetURI());
} catch (const std::runtime_error &e) { } catch (const std::runtime_error &e) {
return false; return false;
} }

View File

@ -93,11 +93,9 @@ sticker_song_find_cb(const char *uri, const char *value, void *user_data)
const Database *db = data->db; const Database *db = data->db;
try { try {
const LightSong *song = db->GetSong(uri, IgnoreError()); const LightSong *song = db->GetSong(uri);
if (song != nullptr) { data->func(*song, value, data->user_data);
data->func(*song, value, data->user_data); db->ReturnSong(song);
db->ReturnSong(song);
}
} catch (const std::runtime_error &e) { } catch (const std::runtime_error &e) {
} }
} }

View File

@ -111,8 +111,7 @@ static const char *uri2 = "foo/bar.ogg";
DetachedSong * DetachedSong *
DatabaseDetachSong(gcc_unused const Database &db, DatabaseDetachSong(gcc_unused const Database &db,
gcc_unused const Storage &_storage, gcc_unused const Storage &_storage,
const char *uri, const char *uri)
gcc_unused Error &error)
{ {
if (strcmp(uri, uri2) == 0) if (strcmp(uri, uri2) == 0)
return new DetachedSong(uri, MakeTag2a()); return new DetachedSong(uri, MakeTag2a());