From a42f9e4ee30bf0d4a09dc5baa5aa9ba9da022988 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 22 Jan 2014 22:40:42 +0100 Subject: LightDirectory: new struct replacing Directory in the DB API --- Makefile.am | 1 + src/DatabasePrint.cxx | 13 +++++---- src/DatabaseVisitor.hxx | 6 ++-- src/Directory.cxx | 11 ++++++-- src/Directory.hxx | 3 ++ src/LightDirectory.hxx | 61 +++++++++++++++++++++++++++++++++++++++++ src/SongPrint.cxx | 1 - src/command/OtherCommands.cxx | 1 + src/db/ProxyDatabasePlugin.cxx | 27 ++++++++---------- src/db/SimpleDatabasePlugin.cxx | 3 +- src/db/UpnpDatabasePlugin.cxx | 13 +++------ test/DumpDatabase.cxx | 11 ++++---- 12 files changed, 109 insertions(+), 42 deletions(-) create mode 100644 src/LightDirectory.hxx diff --git a/Makefile.am b/Makefile.am index b70999b5c..cdeca8dc6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -197,6 +197,7 @@ src_mpd_SOURCES = \ src/SignalHandlers.cxx src/SignalHandlers.hxx \ src/DetachedSong.cxx src/DetachedSong.hxx \ src/LightSong.cxx src/LightSong.hxx \ + src/LightDirectory.hxx \ src/Song.cxx src/Song.hxx \ src/SongUpdate.cxx \ src/SongPrint.cxx src/SongPrint.hxx \ diff --git a/src/DatabasePrint.cxx b/src/DatabasePrint.cxx index ef7ba825b..fc149316d 100644 --- a/src/DatabasePrint.cxx +++ b/src/DatabasePrint.cxx @@ -23,17 +23,18 @@ #include "SongFilter.hxx" #include "SongPrint.hxx" #include "TimePrint.hxx" -#include "Directory.hxx" #include "Client.hxx" #include "tag/Tag.hxx" #include "LightSong.hxx" +#include "LightDirectory.hxx" +#include "PlaylistInfo.hxx" #include "DatabaseGlue.hxx" #include "DatabasePlugin.hxx" #include static bool -PrintDirectoryBrief(Client &client, const Directory &directory) +PrintDirectoryBrief(Client &client, const LightDirectory &directory) { if (!directory.IsRoot()) client_printf(client, "directory: %s\n", directory.GetPath()); @@ -42,7 +43,7 @@ PrintDirectoryBrief(Client &client, const Directory &directory) } static bool -PrintDirectoryFull(Client &client, const Directory &directory) +PrintDirectoryFull(Client &client, const LightDirectory &directory) { if (!directory.IsRoot()) { client_printf(client, "directory: %s\n", directory.GetPath()); @@ -68,7 +69,7 @@ print_playlist_in_directory(Client &client, static void print_playlist_in_directory(Client &client, - const Directory *directory, + const LightDirectory *directory, const char *name_utf8) { if (directory == nullptr || directory->IsRoot()) @@ -105,7 +106,7 @@ PrintSongFull(Client &client, const LightSong &song) static bool PrintPlaylistBrief(Client &client, const PlaylistInfo &playlist, - const Directory &directory) + const LightDirectory &directory) { print_playlist_in_directory(client, &directory, playlist.name.c_str()); return true; @@ -114,7 +115,7 @@ PrintPlaylistBrief(Client &client, static bool PrintPlaylistFull(Client &client, const PlaylistInfo &playlist, - const Directory &directory) + const LightDirectory &directory) { print_playlist_in_directory(client, &directory, playlist.name.c_str()); diff --git a/src/DatabaseVisitor.hxx b/src/DatabaseVisitor.hxx index 486407765..0ec29bf49 100644 --- a/src/DatabaseVisitor.hxx +++ b/src/DatabaseVisitor.hxx @@ -22,14 +22,14 @@ #include -struct Directory; +struct LightDirectory; struct LightSong; struct PlaylistInfo; class Error; -typedef std::function VisitDirectory; +typedef std::function VisitDirectory; typedef std::function VisitSong; -typedef std::function VisitPlaylist; typedef std::function VisitString; diff --git a/src/Directory.cxx b/src/Directory.cxx index b230ac642..14cf88eb5 100644 --- a/src/Directory.cxx +++ b/src/Directory.cxx @@ -19,6 +19,7 @@ #include "config.h" #include "Directory.hxx" +#include "LightDirectory.hxx" #include "SongFilter.hxx" #include "PlaylistVector.hxx" #include "DatabaseLock.hxx" @@ -272,14 +273,14 @@ Directory::Walk(bool recursive, const SongFilter *filter, if (visit_playlist) { for (const PlaylistInfo &p : playlists) - if (!visit_playlist(p, *this, error)) + if (!visit_playlist(p, Export(), error)) return false; } Directory *child; directory_for_each_child(child, *this) { if (visit_directory && - !visit_directory(*child, error)) + !visit_directory(child->Export(), error)) return false; if (recursive && @@ -291,3 +292,9 @@ Directory::Walk(bool recursive, const SongFilter *filter, return true; } + +LightDirectory +Directory::Export() const +{ + return LightDirectory(GetPath(), mtime); +} diff --git a/src/Directory.hxx b/src/Directory.hxx index 54dd58f1c..c64a028ba 100644 --- a/src/Directory.hxx +++ b/src/Directory.hxx @@ -234,6 +234,9 @@ public: VisitDirectory visit_directory, VisitSong visit_song, VisitPlaylist visit_playlist, Error &error) const; + + gcc_pure + LightDirectory Export() const; }; static inline bool diff --git a/src/LightDirectory.hxx b/src/LightDirectory.hxx new file mode 100644 index 000000000..d134151a4 --- /dev/null +++ b/src/LightDirectory.hxx @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2003-2014 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_LIGHT_DIRECTORY_HXX +#define MPD_LIGHT_DIRECTORY_HXX + +#include "Compiler.h" + +#include + +#include + +struct Tag; + +/** + * A reference to a directory. Unlike the #Directory class, this one + * consists only of pointers. It is supposed to be as light as + * possible while still providing all the information MPD has about a + * directory. This class does not manage any memory, and the pointers + * become invalid quickly. Only to be used to pass around during + * well-defined situations. + */ +struct LightDirectory { + const char *uri; + + time_t mtime; + + constexpr LightDirectory(const char *_uri, time_t _mtime) + :uri(_uri), mtime(_mtime) {} + + static constexpr LightDirectory Root() { + return LightDirectory("", 0); + } + + bool IsRoot() const { + return *uri == 0; + } + + gcc_pure + const char *GetPath() const { + return uri; + } +}; + +#endif diff --git a/src/SongPrint.cxx b/src/SongPrint.cxx index 810518c21..cde6ef7d1 100644 --- a/src/SongPrint.cxx +++ b/src/SongPrint.cxx @@ -21,7 +21,6 @@ #include "SongPrint.hxx" #include "LightSong.hxx" #include "DetachedSong.hxx" -#include "Directory.hxx" #include "TimePrint.hxx" #include "TagPrint.hxx" #include "Mapper.hxx" diff --git a/src/command/OtherCommands.cxx b/src/command/OtherCommands.cxx index 0daf62c5a..397e40b00 100644 --- a/src/command/OtherCommands.cxx +++ b/src/command/OtherCommands.cxx @@ -42,6 +42,7 @@ #include "Stats.hxx" #include "Permission.hxx" #include "PlaylistFile.hxx" +#include "PlaylistVector.hxx" #include "ClientFile.hxx" #include "Client.hxx" #include "Idle.hxx" diff --git a/src/db/ProxyDatabasePlugin.cxx b/src/db/ProxyDatabasePlugin.cxx index f65e4f3d0..1b5c3e374 100644 --- a/src/db/ProxyDatabasePlugin.cxx +++ b/src/db/ProxyDatabasePlugin.cxx @@ -23,7 +23,8 @@ #include "DatabaseListener.hxx" #include "DatabaseSelection.hxx" #include "DatabaseError.hxx" -#include "Directory.hxx" +#include "PlaylistInfo.hxx" +#include "LightDirectory.hxx" #include "LightSong.hxx" #include "SongFilter.hxx" #include "Compiler.h" @@ -71,7 +72,6 @@ class ProxyDatabase final : public Database, SocketMonitor, IdleMonitor { unsigned port; struct mpd_connection *connection; - Directory *root; /* this is mutable because GetStats() must be "const" */ mutable time_t update_stamp; @@ -328,7 +328,6 @@ ProxyDatabase::Open(Error &error) if (!Connect(error)) return false; - root = Directory::NewRoot(); update_stamp = 0; return true; @@ -337,8 +336,6 @@ ProxyDatabase::Open(Error &error) void ProxyDatabase::Close() { - delete root; - if (connection != nullptr) Disconnect(); } @@ -515,13 +512,13 @@ ProxyDatabase::ReturnSong(const LightSong *_song) const } static bool -Visit(struct mpd_connection *connection, Directory &root, const char *uri, +Visit(struct mpd_connection *connection, const char *uri, bool recursive, const SongFilter *filter, VisitDirectory visit_directory, VisitSong visit_song, VisitPlaylist visit_playlist, Error &error); static bool -Visit(struct mpd_connection *connection, Directory &root, +Visit(struct mpd_connection *connection, bool recursive, const SongFilter *filter, const struct mpd_directory *directory, VisitDirectory visit_directory, VisitSong visit_song, @@ -530,11 +527,11 @@ Visit(struct mpd_connection *connection, Directory &root, const char *path = mpd_directory_get_path(directory); if (visit_directory && - !visit_directory(Directory(path, &root), error)) + !visit_directory(LightDirectory(path, 0), error)) return false; if (recursive && - !Visit(connection, root, path, recursive, filter, + !Visit(connection, path, recursive, filter, visit_directory, visit_song, visit_playlist, error)) return false; @@ -561,7 +558,7 @@ Visit(const SongFilter *filter, } static bool -Visit(const struct mpd_playlist *playlist, Directory &root, +Visit(const struct mpd_playlist *playlist, VisitPlaylist visit_playlist, Error &error) { if (!visit_playlist) @@ -570,7 +567,7 @@ Visit(const struct mpd_playlist *playlist, Directory &root, PlaylistInfo p(mpd_playlist_get_path(playlist), mpd_playlist_get_last_modified(playlist)); - return visit_playlist(p, root, error); + return visit_playlist(p, LightDirectory::Root(), error); } class ProxyEntity { @@ -612,7 +609,7 @@ ReceiveEntities(struct mpd_connection *connection) } static bool -Visit(struct mpd_connection *connection, Directory &root, const char *uri, +Visit(struct mpd_connection *connection, const char *uri, bool recursive, const SongFilter *filter, VisitDirectory visit_directory, VisitSong visit_song, VisitPlaylist visit_playlist, Error &error) @@ -630,7 +627,7 @@ Visit(struct mpd_connection *connection, Directory &root, const char *uri, break; case MPD_ENTITY_TYPE_DIRECTORY: - if (!Visit(connection, root, recursive, filter, + if (!Visit(connection, recursive, filter, mpd_entity_get_directory(entity), visit_directory, visit_song, visit_playlist, error)) @@ -645,7 +642,7 @@ Visit(struct mpd_connection *connection, Directory &root, const char *uri, break; case MPD_ENTITY_TYPE_PLAYLIST: - if (!Visit(mpd_entity_get_playlist(entity), root, + if (!Visit(mpd_entity_get_playlist(entity), visit_playlist, error)) return false; break; @@ -702,7 +699,7 @@ ProxyDatabase::Visit(const DatabaseSelection &selection, return ::SearchSongs(connection, selection, visit_song, error); /* fall back to recursive walk (slow!) */ - return ::Visit(connection, *root, selection.uri.c_str(), + return ::Visit(connection, selection.uri.c_str(), selection.recursive, selection.filter, visit_directory, visit_song, visit_playlist, error); diff --git a/src/db/SimpleDatabasePlugin.cxx b/src/db/SimpleDatabasePlugin.cxx index 3d947c042..f77d98ea5 100644 --- a/src/db/SimpleDatabasePlugin.cxx +++ b/src/db/SimpleDatabasePlugin.cxx @@ -21,6 +21,7 @@ #include "SimpleDatabasePlugin.hxx" #include "DatabaseSelection.hxx" #include "DatabaseHelpers.hxx" +#include "LightDirectory.hxx" #include "Directory.hxx" #include "Song.hxx" #include "SongFilter.hxx" @@ -265,7 +266,7 @@ SimpleDatabase::Visit(const DatabaseSelection &selection, } if (selection.recursive && visit_directory && - !visit_directory(*directory, error)) + !visit_directory(directory->Export(), error)) return false; return directory->Walk(selection.recursive, selection.filter, diff --git a/src/db/UpnpDatabasePlugin.cxx b/src/db/UpnpDatabasePlugin.cxx index 75d3890ed..844a061c8 100644 --- a/src/db/UpnpDatabasePlugin.cxx +++ b/src/db/UpnpDatabasePlugin.cxx @@ -29,8 +29,7 @@ #include "DatabasePlugin.hxx" #include "DatabaseSelection.hxx" #include "DatabaseError.hxx" -#include "PlaylistVector.hxx" -#include "Directory.hxx" +#include "LightDirectory.hxx" #include "LightSong.hxx" #include "ConfigData.hxx" #include "tag/TagBuilder.hxx" @@ -71,7 +70,6 @@ public: class UpnpDatabase : public Database { LibUPnP *m_lib; UPnPDeviceDirectory *m_superdir; - Directory *m_root; public: static Database *Create(EventLoop &loop, DatabaseListener &listener, @@ -190,7 +188,6 @@ UpnpDatabase::Open(Error &error) return false; } - m_root = Directory::NewRoot(); // Wait for device answers. This should be consistent with the value set // in the lib (currently 2) sleep(2); @@ -200,7 +197,6 @@ UpnpDatabase::Open(Error &error) void UpnpDatabase::Close() { - delete m_root; delete m_superdir; delete m_lib; } @@ -602,9 +598,8 @@ UpnpDatabase::VisitServer(ContentDirectoryService &server, case UPnPDirObject::Type::CONTAINER: if (visit_directory) { - Directory d((selection.uri + "/" + - dirent.name).c_str(), - m_root); + const std::string uri = selection.uri + "/" + dirent.name; + const LightDirectory d(uri.c_str(), 0); if (!visit_directory(d, error)) return false; } @@ -673,7 +668,7 @@ UpnpDatabase::Visit(const DatabaseSelection &selection, // pseudo-directory from the list of servers. if (visit_directory) { for (auto& server : servers) { - Directory d(server.getFriendlyName(), m_root); + const LightDirectory d(server.getFriendlyName(), 0); if (!visit_directory(d, error)) return false; } diff --git a/test/DumpDatabase.cxx b/test/DumpDatabase.cxx index 60c20e4ae..7b959a215 100644 --- a/test/DumpDatabase.cxx +++ b/test/DumpDatabase.cxx @@ -22,7 +22,7 @@ #include "DatabasePlugin.hxx" #include "DatabaseSelection.hxx" #include "DatabaseListener.hxx" -#include "Directory.hxx" +#include "LightDirectory.hxx" #include "LightSong.hxx" #include "PlaylistVector.hxx" #include "ConfigGlobal.hxx" @@ -58,9 +58,9 @@ public: }; static bool -DumpDirectory(const Directory &directory, Error &) +DumpDirectory(const LightDirectory &directory, Error &) { - cout << "D " << directory.path << endl; + cout << "D " << directory.GetPath() << endl; return true; } @@ -76,9 +76,10 @@ DumpSong(const LightSong &song, Error &) static bool DumpPlaylist(const PlaylistInfo &playlist, - const Directory &directory, Error &) + const LightDirectory &directory, Error &) { - cout << "P " << directory.path << "/" << playlist.name.c_str() << endl; + cout << "P " << directory.GetPath() + << "/" << playlist.name.c_str() << endl; return true; } -- cgit v1.2.3