lib/nfs/Manager: add method MakeConnection()
This uses the libnfs function nfs_parse_url_dir() which means MPD gains support for the libnfs arguments like "version". Closes https://github.com/MusicPlayerDaemon/MPD/issues/2039
This commit is contained in:
@@ -26,12 +26,16 @@ extern "C" {
|
||||
#include <nfsc/libnfs-raw-nfs.h>
|
||||
}
|
||||
|
||||
#include <fmt/core.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
using std::string_view_literals::operator""sv;
|
||||
|
||||
class NfsStorage final
|
||||
: public Storage, NfsLease {
|
||||
|
||||
@@ -39,9 +43,16 @@ class NfsStorage final
|
||||
INITIAL, CONNECTING, READY, DELAY,
|
||||
};
|
||||
|
||||
const std::string base;
|
||||
/**
|
||||
* The full configured URL (with all arguemnts). This is used
|
||||
* to reconnect.
|
||||
*/
|
||||
const std::string url;
|
||||
|
||||
const std::string server, export_name;
|
||||
/**
|
||||
* The base URL for building file URLs (without arguments).
|
||||
*/
|
||||
const std::string base;
|
||||
|
||||
NfsConnection *connection;
|
||||
|
||||
@@ -50,18 +61,20 @@ class NfsStorage final
|
||||
|
||||
Mutex mutex;
|
||||
Cond cond;
|
||||
State state = State::INITIAL;
|
||||
State state = State::CONNECTING;
|
||||
std::exception_ptr last_exception;
|
||||
|
||||
public:
|
||||
NfsStorage(EventLoop &_loop, const char *_base,
|
||||
std::string_view _server, std::string_view _export_name)
|
||||
:base(_base),
|
||||
server(_server),
|
||||
export_name(_export_name),
|
||||
defer_connect(_loop, BIND_THIS_METHOD(OnDeferredConnect)),
|
||||
reconnect_timer(_loop, BIND_THIS_METHOD(OnReconnectTimer)) {
|
||||
nfs_init(_loop);
|
||||
NfsStorage(const char *_url, NfsConnection &_connection)
|
||||
:url(_url),
|
||||
base(fmt::format("nfs://{}{}"sv, _connection.GetServer(), _connection.GetExportName())),
|
||||
connection(&_connection),
|
||||
defer_connect(_connection.GetEventLoop(), BIND_THIS_METHOD(OnDeferredConnect)),
|
||||
reconnect_timer(_connection.GetEventLoop(), BIND_THIS_METHOD(OnReconnectTimer))
|
||||
{
|
||||
BlockingCall(GetEventLoop(), [this](){
|
||||
connection->AddLease(*this);
|
||||
});
|
||||
}
|
||||
|
||||
~NfsStorage() override {
|
||||
@@ -142,7 +155,7 @@ private:
|
||||
assert(GetEventLoop().IsInside());
|
||||
|
||||
try {
|
||||
connection = &nfs_get_connection(server, export_name);
|
||||
connection = &nfs_make_connection(url.c_str());
|
||||
} catch (...) {
|
||||
SetState(State::DELAY, std::current_exception());
|
||||
reconnect_timer.Schedule(std::chrono::minutes(10));
|
||||
@@ -394,20 +407,20 @@ NfsStorage::OpenDirectory(std::string_view uri_utf8)
|
||||
static std::unique_ptr<Storage>
|
||||
CreateNfsStorageURI(EventLoop &event_loop, const char *base)
|
||||
{
|
||||
const char *p = StringAfterPrefixCaseASCII(base, "nfs://");
|
||||
if (p == nullptr)
|
||||
if (!StringStartsWithCaseASCII(base, "nfs://"sv))
|
||||
return nullptr;
|
||||
|
||||
const char *slash = std::strchr(p, '/');
|
||||
if (slash == nullptr)
|
||||
throw std::runtime_error("Malformed nfs:// URI");
|
||||
nfs_init(event_loop);
|
||||
|
||||
const std::string_view server{p, slash}, mount{slash};
|
||||
try {
|
||||
auto &connection = nfs_make_connection(base);
|
||||
nfs_set_base(connection.GetServer(), connection.GetExportName());
|
||||
|
||||
nfs_set_base(server, mount);
|
||||
|
||||
return std::make_unique<NfsStorage>(event_loop, base,
|
||||
server, mount);
|
||||
return std::make_unique<NfsStorage>(base, connection);
|
||||
} catch (...) {
|
||||
nfs_finish();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr const char *nfs_prefixes[] = { "nfs://", nullptr };
|
||||
|
Reference in New Issue
Block a user