diff --git a/NEWS b/NEWS index b0f393f57..1c0df1aa7 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,7 @@ ver 0.22.7 (not yet released) * protocol - don't use glibc extension to parse time stamps + - optimize the "albumart" command * input - curl: send user/password in the first request, save one roundtrip * decoder diff --git a/src/client/Client.hxx b/src/client/Client.hxx index deb4b8caa..3e0e2fdec 100644 --- a/src/client/Client.hxx +++ b/src/client/Client.hxx @@ -23,6 +23,7 @@ #include "Message.hxx" #include "command/CommandResult.hxx" #include "command/CommandListBuilder.hxx" +#include "input/LastInputStream.hxx" #include "tag/Mask.hxx" #include "event/FullyBufferedSocket.hxx" #include "event/TimerEvent.hxx" @@ -90,6 +91,13 @@ public: */ size_t binary_limit = 8192; + /** + * This caches the last "albumart" InputStream instance, to + * avoid repeating the search for each chunk requested by this + * client. + */ + LastInputStream last_album_art; + private: static constexpr size_t MAX_SUBSCRIPTIONS = 16; diff --git a/src/client/New.cxx b/src/client/New.cxx index 75019290f..f9633816c 100644 --- a/src/client/New.cxx +++ b/src/client/New.cxx @@ -44,7 +44,8 @@ Client::Client(EventLoop &_loop, Partition &_partition, partition(&_partition), permission(_permission), uid(_uid), - num(_num) + num(_num), + last_album_art(_loop) { timeout_event.Schedule(client_timeout); } diff --git a/src/command/FileCommands.cxx b/src/command/FileCommands.cxx index 7efbb211c..739cc6579 100644 --- a/src/command/FileCommands.cxx +++ b/src/command/FileCommands.cxx @@ -191,9 +191,16 @@ read_stream_art(Response &r, const char *uri, size_t offset) { const auto art_directory = PathTraitsUTF8::GetParent(uri); - Mutex mutex; + // TODO: eliminate this const_cast + auto &client = const_cast(r.GetClient()); - InputStreamPtr is = find_stream_art(art_directory, mutex); + /* to avoid repeating the search for each chunk request by the + same client, use the #LastInputStream class to cache the + #InputStream instance */ + auto *is = client.last_album_art.Open(art_directory, [](std::string_view directory, + Mutex &mutex){ + return find_stream_art(directory, mutex); + }); if (is == nullptr) { r.Error(ACK_ERROR_NO_EXIST, "No file exists"); @@ -219,7 +226,7 @@ read_stream_art(Response &r, const char *uri, size_t offset) std::size_t read_size = 0; if (buffer_size > 0) { - std::unique_lock lock(mutex); + std::unique_lock lock(is->mutex); is->Seek(lock, offset); read_size = is->Read(lock, buffer.get(), buffer_size); }