Decode string context straight to using StorePaths

I gather decoding happens on demand, so I hope don't think this should
have any perf implications one way or the other.
This commit is contained in:
John Ericson 2022-03-12 00:28:00 +00:00
parent 91adfb8894
commit 4d6a3806d2
7 changed files with 38 additions and 24 deletions

View file

@ -21,6 +21,8 @@ struct AttrDb
{ {
std::atomic_bool failed{false}; std::atomic_bool failed{false};
const Store & cfg;
struct State struct State
{ {
SQLite db; SQLite db;
@ -33,8 +35,9 @@ struct AttrDb
std::unique_ptr<Sync<State>> _state; std::unique_ptr<Sync<State>> _state;
AttrDb(const Hash & fingerprint) AttrDb(const Store & cfg, const Hash & fingerprint)
: _state(std::make_unique<Sync<State>>()) : cfg(cfg)
, _state(std::make_unique<Sync<State>>())
{ {
auto state(_state->lock()); auto state(_state->lock());
@ -257,7 +260,7 @@ struct AttrDb
NixStringContext context; NixStringContext context;
if (!queryAttribute.isNull(3)) if (!queryAttribute.isNull(3))
for (auto & s : tokenizeString<std::vector<std::string>>(queryAttribute.getStr(3), ";")) for (auto & s : tokenizeString<std::vector<std::string>>(queryAttribute.getStr(3), ";"))
context.push_back(decodeContext(s)); context.push_back(decodeContext(cfg, s));
return {{rowId, string_t{queryAttribute.getStr(2), context}}}; return {{rowId, string_t{queryAttribute.getStr(2), context}}};
} }
case AttrType::Bool: case AttrType::Bool:
@ -274,10 +277,10 @@ struct AttrDb
} }
}; };
static std::shared_ptr<AttrDb> makeAttrDb(const Hash & fingerprint) static std::shared_ptr<AttrDb> makeAttrDb(const Store & cfg, const Hash & fingerprint)
{ {
try { try {
return std::make_shared<AttrDb>(fingerprint); return std::make_shared<AttrDb>(cfg, fingerprint);
} catch (SQLiteError &) { } catch (SQLiteError &) {
ignoreException(); ignoreException();
return nullptr; return nullptr;
@ -288,7 +291,7 @@ EvalCache::EvalCache(
std::optional<std::reference_wrapper<const Hash>> useCache, std::optional<std::reference_wrapper<const Hash>> useCache,
EvalState & state, EvalState & state,
RootLoader rootLoader) RootLoader rootLoader)
: db(useCache ? makeAttrDb(*useCache) : nullptr) : db(useCache ? makeAttrDb(*state.store, *useCache) : nullptr)
, state(state) , state(state)
, rootLoader(rootLoader) , rootLoader(rootLoader)
{ {
@ -546,7 +549,7 @@ string_t AttrCursor::getStringWithContext()
if (auto s = std::get_if<string_t>(&cachedValue->second)) { if (auto s = std::get_if<string_t>(&cachedValue->second)) {
bool valid = true; bool valid = true;
for (auto & c : s->second) { for (auto & c : s->second) {
if (!root->state.store->isValidPath(root->state.store->parseStorePath(c.first))) { if (!root->state.store->isValidPath(c.first)) {
valid = false; valid = false;
break; break;
} }
@ -563,7 +566,7 @@ string_t AttrCursor::getStringWithContext()
auto & v = forceValue(); auto & v = forceValue();
if (v.type() == nString) if (v.type() == nString)
return {v.string.s, v.getContext()}; return {v.string.s, v.getContext(*root->state.store)};
else if (v.type() == nPath) else if (v.type() == nPath)
return {v.path, {}}; return {v.path, {}};
else else

View file

@ -1903,13 +1903,22 @@ std::string_view EvalState::forceString(Value & v, const Pos & pos)
/* Decode a context string !<name>!<path> into a pair <path, /* Decode a context string !<name>!<path> into a pair <path,
name>. */ name>. */
NixStringContextElem decodeContext(std::string_view s) NixStringContextElem decodeContext(const Store & store, std::string_view s)
{ {
if (s.at(0) == '!') { if (s.at(0) == '!') {
size_t index = s.find("!", 1); size_t index = s.find("!", 1);
return {std::string(s.substr(index + 1)), std::string(s.substr(1, index - 1))}; return {
store.parseStorePath(s.substr(index + 1)),
std::string(s.substr(1, index - 1)),
};
} else } else
return {s.at(0) == '/' ? std::string(s) : std::string(s.substr(1)), ""}; return {
store.parseStorePath(
s.at(0) == '/'
? s
: s.substr(1)),
"",
};
} }
@ -1921,13 +1930,13 @@ void copyContext(const Value & v, PathSet & context)
} }
NixStringContext Value::getContext() NixStringContext Value::getContext(const Store & store)
{ {
NixStringContext res; NixStringContext res;
assert(internalType == tString); assert(internalType == tString);
if (string.context) if (string.context)
for (const char * * p = string.context; *p; ++p) for (const char * * p = string.context; *p; ++p)
res.push_back(decodeContext(*p)); res.push_back(decodeContext(store, *p));
return res; return res;
} }

View file

@ -17,7 +17,7 @@
namespace nix { namespace nix {
class Store; struct Store;
class EvalState; class EvalState;
class StorePath; class StorePath;
enum RepairFlag : bool; enum RepairFlag : bool;
@ -430,7 +430,7 @@ std::string showType(const Value & v);
/* Decode a context string !<name>!<path> into a pair <path, /* Decode a context string !<name>!<path> into a pair <path,
name>. */ name>. */
NixStringContextElem decodeContext(std::string_view s); NixStringContextElem decodeContext(const Store & store, std::string_view s);
/* If `path' refers to a directory, then append "/default.nix". */ /* If `path' refers to a directory, then append "/default.nix". */
Path resolveExprPath(Path path); Path resolveExprPath(Path path);

View file

@ -43,8 +43,8 @@ StringMap EvalState::realiseContext(const PathSet & context)
StringMap res; StringMap res;
for (auto & i : context) { for (auto & i : context) {
auto [ctxS, outputName] = decodeContext(i); auto [ctx, outputName] = decodeContext(*store, i);
auto ctx = store->parseStorePath(ctxS); auto ctxS = store->printStorePath(ctx);
if (!store->isValidPath(ctx)) if (!store->isValidPath(ctx))
throw InvalidPathError(store->printStorePath(ctx)); throw InvalidPathError(store->printStorePath(ctx));
if (!outputName.empty() && ctx.isDerivation()) { if (!outputName.empty() && ctx.isDerivation()) {
@ -1118,8 +1118,8 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
/* Handle derivation outputs of the form !<name>!<path>. */ /* Handle derivation outputs of the form !<name>!<path>. */
else if (path.at(0) == '!') { else if (path.at(0) == '!') {
auto ctx = decodeContext(path); auto ctx = decodeContext(*state.store, path);
drv.inputDrvs[state.store->parseStorePath(ctx.first)].insert(ctx.second); drv.inputDrvs[ctx.first].insert(ctx.second);
} }
/* Otherwise it's a source file. */ /* Otherwise it's a source file. */

View file

@ -82,8 +82,8 @@ static void prim_getContext(EvalState & state, const Pos & pos, Value * * args,
drv = std::string(p, 1); drv = std::string(p, 1);
path = &drv; path = &drv;
} else if (p.at(0) == '!') { } else if (p.at(0) == '!') {
NixStringContextElem ctx = decodeContext(p); NixStringContextElem ctx = decodeContext(*state.store, p);
drv = ctx.first; drv = state.store->printStorePath(ctx.first);
output = ctx.second; output = ctx.second;
path = &drv; path = &drv;
} }

View file

@ -57,6 +57,8 @@ struct ExprLambda;
struct PrimOp; struct PrimOp;
class Symbol; class Symbol;
struct Pos; struct Pos;
class StorePath;
class Store;
class EvalState; class EvalState;
class XMLWriter; class XMLWriter;
class JSONPlaceholder; class JSONPlaceholder;
@ -64,7 +66,7 @@ class JSONPlaceholder;
typedef int64_t NixInt; typedef int64_t NixInt;
typedef double NixFloat; typedef double NixFloat;
typedef std::pair<Path, std::string> NixStringContextElem; typedef std::pair<StorePath, std::string> NixStringContextElem;
typedef std::vector<NixStringContextElem> NixStringContext; typedef std::vector<NixStringContextElem> NixStringContext;
/* External values must descend from ExternalValueBase, so that /* External values must descend from ExternalValueBase, so that
@ -370,7 +372,7 @@ public:
non-trivial. */ non-trivial. */
bool isTrivial() const; bool isTrivial() const;
NixStringContext getContext(); NixStringContext getContext(const Store &);
auto listItems() auto listItems()
{ {

View file

@ -70,7 +70,7 @@ UnresolvedApp Installable::toApp(EvalState & state)
std::vector<StorePathWithOutputs> context2; std::vector<StorePathWithOutputs> context2;
for (auto & [path, name] : context) for (auto & [path, name] : context)
context2.push_back({state.store->parseStorePath(path), {name}}); context2.push_back({path, {name}});
return UnresolvedApp{App { return UnresolvedApp{App {
.context = std::move(context2), .context = std::move(context2),