From 7d5bdf8b5679cc7b2b9b4d9caf5af9ca52211336 Mon Sep 17 00:00:00 2001 From: regnat Date: Tue, 8 Sep 2020 14:50:23 +0200 Subject: Make the store plugins more introspectable Directly register the store classes rather than a function to build an instance of them. This gives the possibility to introspect static members of the class or choose different ways of instantiating them. --- src/libstore/dummy-store.cc | 18 ++++------- src/libstore/http-binary-cache-store.cc | 24 ++++++-------- src/libstore/legacy-ssh-store.cc | 15 +++------ src/libstore/local-binary-cache-store.cc | 23 ++++++------- src/libstore/remote-store.cc | 10 +----- src/libstore/remote-store.hh | 3 ++ src/libstore/s3-binary-cache-store.cc | 15 +++------ src/libstore/ssh-store.cc | 14 +++----- src/libstore/store-api.cc | 55 +++++++++++++++++--------------- src/libstore/store-api.hh | 31 +++++++++++------- src/libstore/store.hh | 9 ++++++ 11 files changed, 105 insertions(+), 112 deletions(-) create mode 100644 src/libstore/store.hh (limited to 'src/libstore') diff --git a/src/libstore/dummy-store.cc b/src/libstore/dummy-store.cc index 7a5744bc1..a677e201e 100644 --- a/src/libstore/dummy-store.cc +++ b/src/libstore/dummy-store.cc @@ -2,17 +2,15 @@ namespace nix { -static std::string uriScheme = "dummy://"; - struct DummyStore : public Store { - DummyStore(const Params & params) + DummyStore(const std::string uri, const Params & params) : Store(params) { } string getUri() override { - return uriScheme; + return uriPrefixes()[0] + "://"; } void queryPathInfoUncached(const StorePath & path, @@ -21,6 +19,10 @@ struct DummyStore : public Store callback(nullptr); } + static std::vector uriPrefixes() { + return {"dummy"}; + } + std::optional queryPathFromHashPart(const std::string & hashPart) override { unsupported("queryPathFromHashPart"); } @@ -48,12 +50,6 @@ struct DummyStore : public Store { unsupported("buildDerivation"); } }; -static RegisterStoreImplementation regStore([]( - const std::string & uri, const Store::Params & params) - -> std::shared_ptr -{ - if (uri != uriScheme) return nullptr; - return std::make_shared(params); -}); +[[maybe_unused]] static RegisterStoreImplementation regStore(); } diff --git a/src/libstore/http-binary-cache-store.cc b/src/libstore/http-binary-cache-store.cc index 1733239fb..6c3a16faf 100644 --- a/src/libstore/http-binary-cache-store.cc +++ b/src/libstore/http-binary-cache-store.cc @@ -24,7 +24,8 @@ private: public: HttpBinaryCacheStore( - const Params & params, const Path & _cacheUri) + const Path & _cacheUri, + const Params & params) : BinaryCacheStore(params) , cacheUri(_cacheUri) { @@ -55,6 +56,13 @@ public: } } + static std::vector uriPrefixes() + { + static bool forceHttp = getEnv("_NIX_FORCE_HTTP") == "1"; + auto ret = std::vector({"http", "https"}); + if (forceHttp) ret.push_back("file"); + return ret; + } protected: void maybeDisable() @@ -162,18 +170,6 @@ protected: }; -static RegisterStoreImplementation regStore([]( - const std::string & uri, const Store::Params & params) - -> std::shared_ptr -{ - static bool forceHttp = getEnv("_NIX_FORCE_HTTP") == "1"; - if (std::string(uri, 0, 7) != "http://" && - std::string(uri, 0, 8) != "https://" && - (!forceHttp || std::string(uri, 0, 7) != "file://")) - return 0; - auto store = std::make_shared(params, uri); - store->init(); - return store; -}); +[[maybe_unused]] static RegisterStoreImplementation regStore(); } diff --git a/src/libstore/legacy-ssh-store.cc b/src/libstore/legacy-ssh-store.cc index dc03313f0..72f28a82d 100644 --- a/src/libstore/legacy-ssh-store.cc +++ b/src/libstore/legacy-ssh-store.cc @@ -9,8 +9,6 @@ namespace nix { -static std::string uriScheme = "ssh://"; - struct LegacySSHStore : public Store { const Setting maxConnections{this, 1, "max-connections", "maximum number of concurrent SSH connections"}; @@ -37,6 +35,9 @@ struct LegacySSHStore : public Store SSHMaster master; + static std::vector uriPrefixes() { return {"ssh"}; } + + LegacySSHStore(const string & host, const Params & params) : Store(params) , host(host) @@ -84,7 +85,7 @@ struct LegacySSHStore : public Store string getUri() override { - return uriScheme + host; + return uriPrefixes()[0] + "://" + host; } void queryPathInfoUncached(const StorePath & path, @@ -325,12 +326,6 @@ public: } }; -static RegisterStoreImplementation regStore([]( - const std::string & uri, const Store::Params & params) - -> std::shared_ptr -{ - if (std::string(uri, 0, uriScheme.size()) != uriScheme) return 0; - return std::make_shared(std::string(uri, uriScheme.size()), params); -}); +[[maybe_unused]] static RegisterStoreImplementation regStore(); } diff --git a/src/libstore/local-binary-cache-store.cc b/src/libstore/local-binary-cache-store.cc index 87d8334d7..752838d3f 100644 --- a/src/libstore/local-binary-cache-store.cc +++ b/src/libstore/local-binary-cache-store.cc @@ -13,7 +13,8 @@ private: public: LocalBinaryCacheStore( - const Params & params, const Path & binaryCacheDir) + const Path & binaryCacheDir, + const Params & params) : BinaryCacheStore(params) , binaryCacheDir(binaryCacheDir) { @@ -26,6 +27,8 @@ public: return "file://" + binaryCacheDir; } + static std::vector uriPrefixes(); + protected: bool fileExists(const std::string & path) override; @@ -85,16 +88,14 @@ bool LocalBinaryCacheStore::fileExists(const std::string & path) return pathExists(binaryCacheDir + "/" + path); } -static RegisterStoreImplementation regStore([]( - const std::string & uri, const Store::Params & params) - -> std::shared_ptr +std::vector LocalBinaryCacheStore::uriPrefixes() { - if (getEnv("_NIX_FORCE_HTTP_BINARY_CACHE_STORE") == "1" || - std::string(uri, 0, 7) != "file://") - return 0; - auto store = std::make_shared(params, std::string(uri, 7)); - store->init(); - return store; -}); + if (getEnv("_NIX_FORCE_HTTP_BINARY_CACHE_STORE") == "1") + return {}; + else + return {"file"}; +} + +[[maybe_unused]] static RegisterStoreImplementation regStore(); } diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc index dc61951d3..824b6b140 100644 --- a/src/libstore/remote-store.cc +++ b/src/libstore/remote-store.cc @@ -982,14 +982,6 @@ std::exception_ptr RemoteStore::Connection::processStderr(Sink * sink, Source * return nullptr; } -static std::string uriScheme = "unix://"; - -static RegisterStoreImplementation regStore([]( - const std::string & uri, const Store::Params & params) - -> std::shared_ptr -{ - if (std::string(uri, 0, uriScheme.size()) != uriScheme) return 0; - return std::make_shared(std::string(uri, uriScheme.size()), params); -}); +[[maybe_unused]] static RegisterStoreImplementation regStore(); } diff --git a/src/libstore/remote-store.hh b/src/libstore/remote-store.hh index 6f05f2197..07cd5daf8 100644 --- a/src/libstore/remote-store.hh +++ b/src/libstore/remote-store.hh @@ -150,6 +150,9 @@ public: std::string getUri() override; + static std::vector uriPrefixes() + { return {"unix"}; } + bool sameMachine() override { return true; } diff --git a/src/libstore/s3-binary-cache-store.cc b/src/libstore/s3-binary-cache-store.cc index a0a446bd3..1bf4d5955 100644 --- a/src/libstore/s3-binary-cache-store.cc +++ b/src/libstore/s3-binary-cache-store.cc @@ -193,7 +193,8 @@ struct S3BinaryCacheStoreImpl : public S3BinaryCacheStore S3Helper s3Helper; S3BinaryCacheStoreImpl( - const Params & params, const std::string & bucketName) + const std::string & bucketName, + const Params & params) : S3BinaryCacheStore(params) , bucketName(bucketName) , s3Helper(profile, region, scheme, endpoint) @@ -426,17 +427,11 @@ struct S3BinaryCacheStoreImpl : public S3BinaryCacheStore return paths; } + static std::vector uriPrefixes() { return {"s3"}; } + }; -static RegisterStoreImplementation regStore([]( - const std::string & uri, const Store::Params & params) - -> std::shared_ptr -{ - if (std::string(uri, 0, 5) != "s3://") return 0; - auto store = std::make_shared(params, std::string(uri, 5)); - store->init(); - return store; -}); +[[maybe_unused]] static RegisterStoreImplementation regStore(); } diff --git a/src/libstore/ssh-store.cc b/src/libstore/ssh-store.cc index 6cb97c1f1..02208ee82 100644 --- a/src/libstore/ssh-store.cc +++ b/src/libstore/ssh-store.cc @@ -8,8 +8,6 @@ namespace nix { -static std::string uriScheme = "ssh-ng://"; - class SSHStore : public RemoteStore { public: @@ -32,9 +30,11 @@ public: { } + static std::vector uriPrefixes() { return {"ssh-ng"}; } + std::string getUri() override { - return uriScheme + host; + return uriPrefixes()[0] + "://" + host; } bool sameMachine() override @@ -76,12 +76,6 @@ ref SSHStore::openConnection() return conn; } -static RegisterStoreImplementation regStore([]( - const std::string & uri, const Store::Params & params) - -> std::shared_ptr -{ - if (std::string(uri, 0, uriScheme.size()) != uriScheme) return 0; - return std::make_shared(std::string(uri, uriScheme.size()), params); -}); +[[maybe_unused]] static RegisterStoreImplementation regStore(); } diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc index b3877487c..4a46b5160 100644 --- a/src/libstore/store-api.cc +++ b/src/libstore/store-api.cc @@ -1009,6 +1009,11 @@ Derivation Store::readDerivation(const StorePath & drvPath) } } +std::shared_ptr Store::getConfig() +{ + return shared_from_this(); +} + } @@ -1019,9 +1024,6 @@ Derivation Store::readDerivation(const StorePath & drvPath) namespace nix { - -RegisterStoreImplementation::Implementations * RegisterStoreImplementation::implementations = 0; - /* Split URI into protocol+hierarchy part and its parameter set. */ std::pair splitUriAndParams(const std::string & uri_) { @@ -1035,24 +1037,6 @@ std::pair splitUriAndParams(const std::string & uri_ return {uri, params}; } -ref openStore(const std::string & uri_, - const Store::Params & extraParams) -{ - auto [uri, uriParams] = splitUriAndParams(uri_); - auto params = extraParams; - params.insert(uriParams.begin(), uriParams.end()); - - for (auto fun : *RegisterStoreImplementation::implementations) { - auto store = fun(uri, params); - if (store) { - store->warnUnknownSettings(); - return ref(store); - } - } - - throw Error("don't know how to open Nix store '%s'", uri); -} - static bool isNonUriPath(const std::string & spec) { return // is not a URL @@ -1080,10 +1064,7 @@ StoreType getStoreType(const std::string & uri, const std::string & stateDir) } } - -static RegisterStoreImplementation regStore([]( - const std::string & uri, const Store::Params & params) - -> std::shared_ptr +std::shared_ptr openFromNonUri(const std::string & uri, const Store::Params & params) { switch (getStoreType(uri, get(params, "state").value_or(settings.nixStateDir))) { case tDaemon: @@ -1098,8 +1079,30 @@ static RegisterStoreImplementation regStore([]( default: return nullptr; } -}); +} + +ref openStore(const std::string & uri_, + const Store::Params & extraParams) +{ + auto [uri, uriParams] = splitUriAndParams(uri_); + auto params = extraParams; + params.insert(uriParams.begin(), uriParams.end()); + + if (auto store = openFromNonUri(uri, params)) { + store->warnUnknownSettings(); + return ref(store); + } + + for (auto implem : *implementations) { + auto store = implem.open(uri, params); + if (store) { + store->warnUnknownSettings(); + return ref(store); + } + } + throw Error("don't know how to open Nix store '%s'", uri); +} std::list> getDefaultSubstituters() { diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh index 8b42aa6d2..28365542d 100644 --- a/src/libstore/store-api.hh +++ b/src/libstore/store-api.hh @@ -33,6 +33,7 @@ MakeError(SubstituteGone, Error); MakeError(SubstituterDisabled, Error); MakeError(BadStorePath, Error); +MakeError(InvalidStoreURI, Error); class FSAccessor; class NarInfoDiskCache; @@ -199,6 +200,8 @@ protected: Store(const Params & params); + std::shared_ptr getConfig(); + public: virtual ~Store() { } @@ -744,25 +747,31 @@ StoreType getStoreType(const std::string & uri = settings.storeUri.get(), ‘substituters’ option and various legacy options. */ std::list> getDefaultSubstituters(); +struct StoreFactory +{ + std::vector uriPrefixes; + std::function (const std::string & uri, const Store::Params & params)> open; +}; +typedef std::vector Implementations; +static Implementations * implementations = new Implementations; -/* Store implementation registration. */ -typedef std::function( - const std::string & uri, const Store::Params & params)> OpenStore; - +template struct RegisterStoreImplementation { - typedef std::vector Implementations; - static Implementations * implementations; - - RegisterStoreImplementation(OpenStore fun) + RegisterStoreImplementation() { - if (!implementations) implementations = new Implementations; - implementations->push_back(fun); + StoreFactory factory{ + .uriPrefixes = T::uriPrefixes(), + .open = + ([](const std::string & uri, const Store::Params & params) + -> std::shared_ptr + { return std::make_shared(uri, params); }) + }; + implementations->push_back(factory); } }; - /* Display a set of paths in human-readable form (i.e., between quotes and separated by commas). */ string showPaths(const PathSet & paths); diff --git a/src/libstore/store.hh b/src/libstore/store.hh new file mode 100644 index 000000000..bc73963f3 --- /dev/null +++ b/src/libstore/store.hh @@ -0,0 +1,9 @@ +#pragma once + +namespace nix { + +template class BasicStore; +class StoreConfig; +typedef BasicStore Store; + +} -- cgit v1.2.3