From b64d01677bf6175216c0f5274e05e55d092f2766 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 15 May 2024 21:46:38 +0200 Subject: [PATCH] storage/nfs: optimize OpenFile() --- src/input/plugins/NfsInputPlugin.cxx | 16 +++++++++++++ src/input/plugins/NfsInputPlugin.hxx | 14 ++++++++--- src/lib/nfs/FileReader.cxx | 36 +++++++++++++++++++++++----- src/lib/nfs/FileReader.hxx | 7 +++++- src/storage/plugins/NfsStorage.cxx | 7 +++--- 5 files changed, 67 insertions(+), 13 deletions(-) diff --git a/src/input/plugins/NfsInputPlugin.cxx b/src/input/plugins/NfsInputPlugin.cxx index e48747a0a..7306d826e 100644 --- a/src/input/plugins/NfsInputPlugin.cxx +++ b/src/input/plugins/NfsInputPlugin.cxx @@ -31,6 +31,15 @@ public: NFS_MAX_BUFFERED, NFS_RESUME_AT) {} + NfsInputStream(NfsConnection &_connection, std::string_view _path, + Mutex &_mutex) noexcept + :NfsFileReader(_connection, _path), + AsyncInputStream(NfsFileReader::GetEventLoop(), + NfsFileReader::GetAbsoluteUri(), + _mutex, + NFS_MAX_BUFFERED, + NFS_RESUME_AT) {} + ~NfsInputStream() override { DeferClose(); } @@ -225,3 +234,10 @@ const InputPlugin input_plugin_nfs = { input_nfs_open, nullptr }; + +InputStreamPtr +OpenNfsInputStream(NfsConnection &connection, std::string_view path, + Mutex &mutex) +{ + return std::make_unique(connection, path, mutex); +} diff --git a/src/input/plugins/NfsInputPlugin.hxx b/src/input/plugins/NfsInputPlugin.hxx index 86be94bb3..f2cf017a6 100644 --- a/src/input/plugins/NfsInputPlugin.hxx +++ b/src/input/plugins/NfsInputPlugin.hxx @@ -1,9 +1,17 @@ // SPDX-License-Identifier: GPL-2.0-or-later // Copyright The Music Player Daemon Project -#ifndef MPD_INPUT_NFS_H -#define MPD_INPUT_NFS_H +#pragma once + +#include "input/Ptr.hxx" +#include "thread/Mutex.hxx" + +#include + +class NfsConnection; extern const struct InputPlugin input_plugin_nfs; -#endif +InputStreamPtr +OpenNfsInputStream(NfsConnection &connection, std::string_view path, + Mutex &mutex); diff --git a/src/lib/nfs/FileReader.cxx b/src/lib/nfs/FileReader.cxx index d75d08811..ae8c75fed 100644 --- a/src/lib/nfs/FileReader.cxx +++ b/src/lib/nfs/FileReader.cxx @@ -10,6 +10,8 @@ #include // for struct nfs_stat_64 +#include + #include #include #include @@ -18,16 +20,37 @@ #include #include // for S_ISREG() +using std::string_view_literals::operator""sv; + NfsFileReader::NfsFileReader() noexcept :defer_open(nfs_get_event_loop(), BIND_THIS_METHOD(OnDeferredOpen)) { } +NfsFileReader::NfsFileReader(NfsConnection &_connection, + std::string_view _path) noexcept + :state(State::DEFER), + path(_path), + connection(&_connection), + defer_open(_connection.GetEventLoop(), BIND_THIS_METHOD(OnDeferredOpen)) +{ + defer_open.Schedule(); +} + NfsFileReader::~NfsFileReader() noexcept { assert(state == State::INITIAL); } +std::string +NfsFileReader::GetAbsoluteUri() const noexcept +{ + return fmt::format("nfs://{}{}/{}"sv, + connection != nullptr ? connection->GetServer() : server, + connection != nullptr ? connection->GetExportName() : export_name, + path); +} + void NfsFileReader::Close() noexcept { @@ -293,12 +316,13 @@ NfsFileReader::OnDeferredOpen() noexcept { assert(state == State::DEFER); - try { - connection = &nfs_get_connection(server, export_name); - } catch (...) { - OnNfsFileError(std::current_exception()); - return; - } + if (connection == nullptr) + try { + connection = &nfs_get_connection(server, export_name); + } catch (...) { + OnNfsFileError(std::current_exception()); + return; + } connection->AddLease(*this); state = State::MOUNT; diff --git a/src/lib/nfs/FileReader.hxx b/src/lib/nfs/FileReader.hxx index 37c8c3b49..f13889c7f 100644 --- a/src/lib/nfs/FileReader.hxx +++ b/src/lib/nfs/FileReader.hxx @@ -45,7 +45,7 @@ class NfsFileReader : NfsLease, NfsCallback { std::string server, export_name, path; - NfsConnection *connection; + NfsConnection *connection = nullptr; nfsfh *fh; @@ -60,12 +60,17 @@ class NfsFileReader : NfsLease, NfsCallback { public: NfsFileReader() noexcept; + explicit NfsFileReader(NfsConnection &_connection, + std::string_view _path) noexcept; ~NfsFileReader() noexcept; auto &GetEventLoop() const noexcept { return defer_open.GetEventLoop(); } + [[nodiscard]] [[gnu::pure]] + std::string GetAbsoluteUri() const noexcept; + void Close() noexcept; void DeferClose() noexcept; diff --git a/src/storage/plugins/NfsStorage.cxx b/src/storage/plugins/NfsStorage.cxx index f9900548e..5824f487b 100644 --- a/src/storage/plugins/NfsStorage.cxx +++ b/src/storage/plugins/NfsStorage.cxx @@ -12,6 +12,7 @@ #include "lib/nfs/Connection.hxx" #include "lib/nfs/Glue.hxx" #include "input/InputStream.hxx" +#include "input/plugins/NfsInputPlugin.hxx" #include "fs/AllocatedPath.hxx" #include "thread/Mutex.hxx" #include "thread/Cond.hxx" @@ -252,9 +253,9 @@ NfsStorage::MapToRelativeUTF8(std::string_view uri_utf8) const noexcept InputStreamPtr NfsStorage::OpenFile(std::string_view uri_utf8, Mutex &_mutex) { - // TODO create NfsInputStream directly - auto uri = MapUTF8(uri_utf8); - return InputStream::Open(uri.c_str(), _mutex); + WaitConnected(); + + return OpenNfsInputStream(*connection, uri_utf8, _mutex); } static void