diff options
Diffstat (limited to 'src/libstore/store-api.cc')
-rw-r--r-- | src/libstore/store-api.cc | 181 |
1 files changed, 167 insertions, 14 deletions
diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc index cc91ed287768..463e132e0299 100644 --- a/src/libstore/store-api.cc +++ b/src/libstore/store-api.cc @@ -2,6 +2,7 @@ #include "globals.hh" #include "store-api.hh" #include "util.hh" +#include "nar-info-disk-cache.hh" namespace nix { @@ -16,6 +17,7 @@ bool isInStore(const Path & path) bool isStorePath(const Path & path) { return isInStore(path) + && path.size() >= settings.nixStore.size() + 1 + storePathHashLen && path.find('/', settings.nixStore.size() + 1) == Path::npos; } @@ -62,13 +64,16 @@ Path followLinksToStorePath(const Path & path) string storePathToName(const Path & path) { assertStorePath(path); - return string(path, settings.nixStore.size() + storePathHashLen + 2); + auto l = settings.nixStore.size() + 1 + storePathHashLen; + assert(path.size() >= l); + return path.size() == l ? "" : string(path, l + 1); } string storePathToHash(const Path & path) { assertStorePath(path); + assert(path.size() >= settings.nixStore.size() + 1 + storePathHashLen); return string(path, settings.nixStore.size() + 1, storePathHashLen); } @@ -225,10 +230,89 @@ Path computeStorePathForText(const string & name, const string & s, } -void Store::queryReferences(const Path & path, PathSet & references) +std::string Store::getUri() { - ValidPathInfo info = queryPathInfo(path); - references.insert(info.references.begin(), info.references.end()); + return ""; +} + + +bool Store::isValidPath(const Path & storePath) +{ + auto hashPart = storePathToHash(storePath); + + { + auto state_(state.lock()); + auto res = state_->pathInfoCache.get(hashPart); + if (res) { + stats.narInfoReadAverted++; + return *res != 0; + } + } + + if (diskCache) { + auto res = diskCache->lookupNarInfo(getUri(), hashPart); + if (res.first != NarInfoDiskCache::oUnknown) { + stats.narInfoReadAverted++; + auto state_(state.lock()); + state_->pathInfoCache.upsert(hashPart, + res.first == NarInfoDiskCache::oInvalid ? 0 : res.second); + return res.first == NarInfoDiskCache::oValid; + } + } + + return isValidPathUncached(storePath); + + // FIXME: insert result into NARExistence table of diskCache. +} + + +ref<const ValidPathInfo> Store::queryPathInfo(const Path & storePath) +{ + auto hashPart = storePathToHash(storePath); + + { + auto state_(state.lock()); + auto res = state_->pathInfoCache.get(hashPart); + if (res) { + stats.narInfoReadAverted++; + if (!*res) + throw InvalidPath(format("path ‘%s’ is not valid") % storePath); + return ref<ValidPathInfo>(*res); + } + } + + if (diskCache) { + auto res = diskCache->lookupNarInfo(getUri(), hashPart); + if (res.first != NarInfoDiskCache::oUnknown) { + stats.narInfoReadAverted++; + auto state_(state.lock()); + state_->pathInfoCache.upsert(hashPart, + res.first == NarInfoDiskCache::oInvalid ? 0 : res.second); + if (res.first == NarInfoDiskCache::oInvalid || + (res.second->path != storePath && storePathToName(storePath) != "")) + throw InvalidPath(format("path ‘%s’ is not valid") % storePath); + return ref<ValidPathInfo>(res.second); + } + } + + auto info = queryPathInfoUncached(storePath); + + if (diskCache && info) + diskCache->upsertNarInfo(getUri(), hashPart, info); + + { + auto state_(state.lock()); + state_->pathInfoCache.upsert(hashPart, info); + } + + if (!info + || (info->path != storePath && storePathToName(storePath) != "")) + { + stats.narInfoMissing++; + throw InvalidPath(format("path ‘%s’ is not valid") % storePath); + } + + return ref<ValidPathInfo>(info); } @@ -243,19 +327,19 @@ string Store::makeValidityRegistration(const PathSet & paths, for (auto & i : paths) { s += i + "\n"; - ValidPathInfo info = queryPathInfo(i); + auto info = queryPathInfo(i); if (showHash) { - s += printHash(info.narHash) + "\n"; - s += (format("%1%\n") % info.narSize).str(); + s += printHash(info->narHash) + "\n"; + s += (format("%1%\n") % info->narSize).str(); } - Path deriver = showDerivers ? info.deriver : ""; + Path deriver = showDerivers ? info->deriver : ""; s += deriver + "\n"; - s += (format("%1%\n") % info.references.size()).str(); + s += (format("%1%\n") % info->references.size()).str(); - for (auto & j : info.references) + for (auto & j : info->references) s += j + "\n"; } @@ -263,6 +347,16 @@ string Store::makeValidityRegistration(const PathSet & paths, } +const Store::Stats & Store::getStats() +{ + { + auto state_(state.lock()); + stats.pathInfoCacheSize = state_->pathInfoCache.size(); + } + return stats; +} + + ValidPathInfo decodeValidPathInfo(std::istream & str, bool hashGiven) { ValidPathInfo info; @@ -312,7 +406,7 @@ void Store::exportPaths(const Paths & paths, std::string ValidPathInfo::fingerprint() const { - if (narSize == 0 || narHash.type == htUnknown) + if (narSize == 0 || !narHash) throw Error(format("cannot calculate fingerprint of path ‘%s’ because its size/hash is not known") % path); return @@ -345,6 +439,15 @@ bool ValidPathInfo::checkSignature(const PublicKeys & publicKeys, const std::str } +Strings ValidPathInfo::shortRefs() const +{ + Strings refs; + for (auto & r : references) + refs.push_back(baseNameOf(r)); + return refs; +} + + } @@ -358,10 +461,22 @@ namespace nix { RegisterStoreImplementation::Implementations * RegisterStoreImplementation::implementations = 0; -ref<Store> openStoreAt(const std::string & uri) +ref<Store> openStoreAt(const std::string & uri_) { + auto uri(uri_); + StoreParams params; + auto q = uri.find('?'); + if (q != std::string::npos) { + for (auto s : tokenizeString<Strings>(uri.substr(q + 1), "&")) { + auto e = s.find('='); + if (e != std::string::npos) + params[s.substr(0, e)] = s.substr(e + 1); + } + uri = uri_.substr(0, q); + } + for (auto fun : *RegisterStoreImplementation::implementations) { - auto store = fun(uri); + auto store = fun(uri, params); if (store) return ref<Store>(store); } @@ -375,7 +490,10 @@ ref<Store> openStore() } -static RegisterStoreImplementation regStore([](const std::string & uri) -> std::shared_ptr<Store> { +static RegisterStoreImplementation regStore([]( + const std::string & uri, const StoreParams & params) + -> std::shared_ptr<Store> +{ enum { mDaemon, mLocal, mAuto } mode; if (uri == "daemon") mode = mDaemon; @@ -398,4 +516,39 @@ static RegisterStoreImplementation regStore([](const std::string & uri) -> std:: }); +std::list<ref<Store>> getDefaultSubstituters() +{ + struct State { + bool done = false; + std::list<ref<Store>> stores; + }; + static Sync<State> state_; + + auto state(state_.lock()); + + if (state->done) return state->stores; + + StringSet done; + + auto addStore = [&](const std::string & uri) { + if (done.count(uri)) return; + done.insert(uri); + state->stores.push_back(openStoreAt(uri)); + }; + + for (auto uri : settings.get("substituters", Strings())) + addStore(uri); + + for (auto uri : settings.get("binary-caches", Strings())) + addStore(uri); + + for (auto uri : settings.get("extra-binary-caches", Strings())) + addStore(uri); + + state->done = true; + + return state->stores; +} + + } |