aboutsummaryrefslogtreecommitdiff
path: root/src/libexpr/flake
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2020-04-20 13:14:59 +0200
committerEelco Dolstra <edolstra@gmail.com>2020-04-20 13:14:59 +0200
commit42a12f9232c8e3373df7f4660b2dfd837db92e4b (patch)
tree6756ed86b59fb603d68742076c2405f77887073e /src/libexpr/flake
parent539a9c1c5f0e4c9ab2262e7cf48460e02b8b0e12 (diff)
Move eval-cache.{cc,hh}
Diffstat (limited to 'src/libexpr/flake')
-rw-r--r--src/libexpr/flake/eval-cache.cc460
-rw-r--r--src/libexpr/flake/eval-cache.hh103
2 files changed, 0 insertions, 563 deletions
diff --git a/src/libexpr/flake/eval-cache.cc b/src/libexpr/flake/eval-cache.cc
deleted file mode 100644
index e17dbde84..000000000
--- a/src/libexpr/flake/eval-cache.cc
+++ /dev/null
@@ -1,460 +0,0 @@
-#include "eval-cache.hh"
-#include "sqlite.hh"
-#include "eval.hh"
-#include "eval-inline.hh"
-
-namespace nix::eval_cache {
-
-// FIXME: inefficient representation of attrs
-static const char * schema = R"sql(
-create table if not exists Attributes (
- parent integer not null,
- name text,
- type integer not null,
- value text,
- primary key (parent, name)
-);
-)sql";
-
-struct AttrDb
-{
- struct State
- {
- SQLite db;
- SQLiteStmt insertAttribute;
- SQLiteStmt queryAttribute;
- SQLiteStmt queryAttributes;
- std::unique_ptr<SQLiteTxn> txn;
- };
-
- std::unique_ptr<Sync<State>> _state;
-
- AttrDb(const Hash & fingerprint)
- : _state(std::make_unique<Sync<State>>())
- {
- auto state(_state->lock());
-
- Path cacheDir = getCacheDir() + "/nix/eval-cache-v1";
- createDirs(cacheDir);
-
- Path dbPath = cacheDir + "/" + fingerprint.to_string(Base16, false) + ".sqlite";
-
- state->db = SQLite(dbPath);
- state->db.isCache();
- state->db.exec(schema);
-
- state->insertAttribute.create(state->db,
- "insert or replace into Attributes(parent, name, type, value) values (?, ?, ?, ?)");
-
- state->queryAttribute.create(state->db,
- "select rowid, type, value from Attributes where parent = ? and name = ?");
-
- state->queryAttributes.create(state->db,
- "select name from Attributes where parent = ?");
-
- state->txn = std::make_unique<SQLiteTxn>(state->db);
- }
-
- ~AttrDb()
- {
- try {
- auto state(_state->lock());
- state->txn->commit();
- state->txn.reset();
- } catch (...) {
- ignoreException();
- }
- }
-
- AttrId setAttrs(
- AttrKey key,
- const std::vector<Symbol> & attrs)
- {
- auto state(_state->lock());
-
- state->insertAttribute.use()
- (key.first)
- (key.second)
- (AttrType::FullAttrs)
- (0, false).exec();
-
- AttrId rowId = state->db.getLastInsertedRowId();
- assert(rowId);
-
- for (auto & attr : attrs)
- state->insertAttribute.use()
- (rowId)
- (attr)
- (AttrType::Placeholder)
- (0, false).exec();
-
- return rowId;
- }
-
- AttrId setString(
- AttrKey key,
- std::string_view s)
- {
- auto state(_state->lock());
-
- state->insertAttribute.use()
- (key.first)
- (key.second)
- (AttrType::String)
- (s).exec();
-
- return state->db.getLastInsertedRowId();
- }
-
- AttrId setPlaceholder(AttrKey key)
- {
- auto state(_state->lock());
-
- state->insertAttribute.use()
- (key.first)
- (key.second)
- (AttrType::Placeholder)
- (0, false).exec();
-
- return state->db.getLastInsertedRowId();
- }
-
- AttrId setMissing(AttrKey key)
- {
- auto state(_state->lock());
-
- state->insertAttribute.use()
- (key.first)
- (key.second)
- (AttrType::Missing)
- (0, false).exec();
-
- return state->db.getLastInsertedRowId();
- }
-
- AttrId setMisc(AttrKey key)
- {
- auto state(_state->lock());
-
- state->insertAttribute.use()
- (key.first)
- (key.second)
- (AttrType::Misc)
- (0, false).exec();
-
- return state->db.getLastInsertedRowId();
- }
-
- AttrId setFailed(AttrKey key)
- {
- auto state(_state->lock());
-
- state->insertAttribute.use()
- (key.first)
- (key.second)
- (AttrType::Failed)
- (0, false).exec();
-
- return state->db.getLastInsertedRowId();
- }
-
- std::optional<std::pair<AttrId, AttrValue>> getAttr(
- AttrKey key,
- SymbolTable & symbols)
- {
- auto state(_state->lock());
-
- auto queryAttribute(state->queryAttribute.use()(key.first)(key.second));
- if (!queryAttribute.next()) return {};
-
- auto rowId = (AttrType) queryAttribute.getInt(0);
- auto type = (AttrType) queryAttribute.getInt(1);
-
- if (type == AttrType::Placeholder)
- return {{rowId, placeholder_t()}};
- else if (type == AttrType::FullAttrs) {
- // FIXME: expensive, should separate this out.
- std::vector<Symbol> attrs;
- auto queryAttributes(state->queryAttributes.use()(rowId));
- while (queryAttributes.next())
- attrs.push_back(symbols.create(queryAttributes.getStr(0)));
- return {{rowId, attrs}};
- } else if (type == AttrType::String) {
- return {{rowId, queryAttribute.getStr(2)}};
- } else if (type == AttrType::Missing) {
- return {{rowId, missing_t()}};
- } else if (type == AttrType::Misc) {
- return {{rowId, misc_t()}};
- } else if (type == AttrType::Failed) {
- return {{rowId, failed_t()}};
- } else
- throw Error("unexpected type in evaluation cache");
- }
-};
-
-EvalCache::EvalCache(
- bool useCache,
- const Hash & fingerprint,
- EvalState & state,
- RootLoader rootLoader)
- : db(useCache ? std::make_shared<AttrDb>(fingerprint) : nullptr)
- , state(state)
- , rootLoader(rootLoader)
-{
-}
-
-Value * EvalCache::getRootValue()
-{
- if (!value) {
- debug("getting root value");
- value = allocRootValue(rootLoader());
- }
- return *value;
-}
-
-std::shared_ptr<AttrCursor> EvalCache::getRoot()
-{
- return std::make_shared<AttrCursor>(ref(shared_from_this()), std::nullopt);
-}
-
-AttrCursor::AttrCursor(
- ref<EvalCache> root,
- Parent parent,
- Value * value,
- std::optional<std::pair<AttrId, AttrValue>> && cachedValue)
- : root(root), parent(parent), cachedValue(std::move(cachedValue))
-{
- if (value)
- _value = allocRootValue(value);
-}
-
-AttrKey AttrCursor::getKey()
-{
- if (!parent)
- return {0, root->state.sEpsilon};
- if (!parent->first->cachedValue) {
- parent->first->cachedValue = root->db->getAttr(
- parent->first->getKey(), root->state.symbols);
- assert(parent->first->cachedValue);
- }
- return {parent->first->cachedValue->first, parent->second};
-}
-
-Value & AttrCursor::getValue()
-{
- if (!_value) {
- if (parent) {
- auto & vParent = parent->first->getValue();
- root->state.forceAttrs(vParent);
- auto attr = vParent.attrs->get(parent->second);
- if (!attr)
- throw Error("attribute '%s' is unexpectedly missing", getAttrPathStr());
- _value = allocRootValue(attr->value);
- } else
- _value = allocRootValue(root->getRootValue());
- }
- return **_value;
-}
-
-std::vector<Symbol> AttrCursor::getAttrPath() const
-{
- if (parent) {
- auto attrPath = parent->first->getAttrPath();
- attrPath.push_back(parent->second);
- return attrPath;
- } else
- return {};
-}
-
-std::vector<Symbol> AttrCursor::getAttrPath(Symbol name) const
-{
- auto attrPath = getAttrPath();
- attrPath.push_back(name);
- return attrPath;
-}
-
-std::string AttrCursor::getAttrPathStr() const
-{
- return concatStringsSep(".", getAttrPath());
-}
-
-std::string AttrCursor::getAttrPathStr(Symbol name) const
-{
- return concatStringsSep(".", getAttrPath(name));
-}
-
-Value & AttrCursor::forceValue()
-{
- debug("evaluating uncached attribute %s", getAttrPathStr());
-
- auto & v = getValue();
-
- try {
- root->state.forceValue(v);
- } catch (EvalError &) {
- debug("setting '%s' to failed", getAttrPathStr());
- if (root->db)
- cachedValue = {root->db->setFailed(getKey()), failed_t()};
- throw;
- }
-
- if (root->db && (!cachedValue || std::get_if<placeholder_t>(&cachedValue->second))) {
- if (v.type == tString)
- cachedValue = {root->db->setString(getKey(), v.string.s), v.string.s};
- else if (v.type == tAttrs)
- ; // FIXME: do something?
- else
- cachedValue = {root->db->setMisc(getKey()), misc_t()};
- }
-
- return v;
-}
-
-std::shared_ptr<AttrCursor> AttrCursor::maybeGetAttr(Symbol name)
-{
- if (root->db) {
- if (!cachedValue)
- cachedValue = root->db->getAttr(getKey(), root->state.symbols);
-
- if (cachedValue) {
- if (auto attrs = std::get_if<std::vector<Symbol>>(&cachedValue->second)) {
- for (auto & attr : *attrs)
- if (attr == name)
- return std::make_shared<AttrCursor>(root, std::make_pair(shared_from_this(), name));
- return nullptr;
- } else if (std::get_if<placeholder_t>(&cachedValue->second)) {
- auto attr = root->db->getAttr({cachedValue->first, name}, root->state.symbols);
- if (attr) {
- if (std::get_if<missing_t>(&attr->second))
- return nullptr;
- else if (std::get_if<failed_t>(&attr->second))
- throw EvalError("cached failure of attribute '%s'", getAttrPathStr(name));
- else
- return std::make_shared<AttrCursor>(root,
- std::make_pair(shared_from_this(), name), nullptr, std::move(attr));
- }
- // Incomplete attrset, so need to fall thru and
- // evaluate to see whether 'name' exists
- } else
- return nullptr;
- //throw TypeError("'%s' is not an attribute set", getAttrPathStr());
- }
- }
-
- auto & v = forceValue();
-
- if (v.type != tAttrs)
- return nullptr;
- //throw TypeError("'%s' is not an attribute set", getAttrPathStr());
-
- auto attr = v.attrs->get(name);
-
- if (!attr) {
- if (root->db) {
- if (!cachedValue)
- cachedValue = {root->db->setPlaceholder(getKey()), placeholder_t()};
- root->db->setMissing({cachedValue->first, name});
- }
- return nullptr;
- }
-
- std::optional<std::pair<AttrId, AttrValue>> cachedValue2;
- if (root->db) {
- if (!cachedValue)
- cachedValue = {root->db->setPlaceholder(getKey()), placeholder_t()};
- cachedValue2 = {root->db->setPlaceholder({cachedValue->first, name}), placeholder_t()};
- }
-
- return std::make_shared<AttrCursor>(
- root, std::make_pair(shared_from_this(), name), attr->value, std::move(cachedValue2));
-}
-
-std::shared_ptr<AttrCursor> AttrCursor::maybeGetAttr(std::string_view name)
-{
- return maybeGetAttr(root->state.symbols.create(name));
-}
-
-std::shared_ptr<AttrCursor> AttrCursor::getAttr(Symbol name)
-{
- auto p = maybeGetAttr(name);
- if (!p)
- throw Error("attribute '%s' does not exist", getAttrPathStr(name));
- return p;
-}
-
-std::shared_ptr<AttrCursor> AttrCursor::getAttr(std::string_view name)
-{
- return getAttr(root->state.symbols.create(name));
-}
-
-std::shared_ptr<AttrCursor> AttrCursor::findAlongAttrPath(const std::vector<Symbol> & attrPath)
-{
- auto res = shared_from_this();
- for (auto & attr : attrPath) {
- res = res->maybeGetAttr(attr);
- if (!res) return {};
- }
- return res;
-}
-
-std::string AttrCursor::getString()
-{
- if (root->db) {
- if (!cachedValue)
- cachedValue = root->db->getAttr(getKey(), root->state.symbols);
- if (cachedValue && !std::get_if<placeholder_t>(&cachedValue->second)) {
- if (auto s = std::get_if<std::string>(&cachedValue->second)) {
- debug("using cached string attribute '%s'", getAttrPathStr());
- return *s;
- } else
- throw TypeError("'%s' is not a string", getAttrPathStr());
- }
- }
-
- auto & v = forceValue();
-
- if (v.type != tString)
- throw TypeError("'%s' is not a string", getAttrPathStr());
-
- return v.string.s;
-}
-
-std::vector<Symbol> AttrCursor::getAttrs()
-{
- if (root->db) {
- if (!cachedValue)
- cachedValue = root->db->getAttr(getKey(), root->state.symbols);
- if (cachedValue && !std::get_if<placeholder_t>(&cachedValue->second)) {
- if (auto attrs = std::get_if<std::vector<Symbol>>(&cachedValue->second)) {
- debug("using cached attrset attribute '%s'", getAttrPathStr());
- return *attrs;
- } else
- throw TypeError("'%s' is not an attribute set", getAttrPathStr());
- }
- }
-
- auto & v = forceValue();
-
- if (v.type != tAttrs)
- throw TypeError("'%s' is not an attribute set", getAttrPathStr());
-
- std::vector<Symbol> attrs;
- for (auto & attr : *getValue().attrs)
- attrs.push_back(attr.name);
- std::sort(attrs.begin(), attrs.end(), [](const Symbol & a, const Symbol & b) {
- return (const string &) a < (const string &) b;
- });
-
- if (root->db)
- cachedValue = {root->db->setAttrs(getKey(), attrs), attrs};
-
- return attrs;
-}
-
-bool AttrCursor::isDerivation()
-{
- auto aType = maybeGetAttr("type");
- return aType && aType->getString() == "derivation";
-}
-
-}
diff --git a/src/libexpr/flake/eval-cache.hh b/src/libexpr/flake/eval-cache.hh
deleted file mode 100644
index a2c21b6ea..000000000
--- a/src/libexpr/flake/eval-cache.hh
+++ /dev/null
@@ -1,103 +0,0 @@
-#pragma once
-
-#include "sync.hh"
-#include "hash.hh"
-#include "eval.hh"
-
-#include <variant>
-
-namespace nix::eval_cache {
-
-class AttrDb;
-class AttrCursor;
-
-class EvalCache : public std::enable_shared_from_this<EvalCache>
-{
- friend class AttrCursor;
-
- std::shared_ptr<AttrDb> db;
- EvalState & state;
- typedef std::function<Value *()> RootLoader;
- RootLoader rootLoader;
- RootValue value;
-
- Value * getRootValue();
-
-public:
-
- EvalCache(
- bool useCache,
- const Hash & fingerprint,
- EvalState & state,
- RootLoader rootLoader);
-
- std::shared_ptr<AttrCursor> getRoot();
-};
-
-enum AttrType {
- Placeholder = 0,
- FullAttrs = 1,
- String = 2,
- Missing = 3,
- Misc = 4,
- Failed = 5,
-};
-
-struct placeholder_t {};
-struct missing_t {};
-struct misc_t {};
-struct failed_t {};
-typedef uint64_t AttrId;
-typedef std::pair<AttrId, Symbol> AttrKey;
-typedef std::variant<std::vector<Symbol>, std::string, placeholder_t, missing_t, misc_t, failed_t> AttrValue;
-
-class AttrCursor : public std::enable_shared_from_this<AttrCursor>
-{
- friend class EvalCache;
-
- ref<EvalCache> root;
- typedef std::optional<std::pair<std::shared_ptr<AttrCursor>, Symbol>> Parent;
- Parent parent;
- RootValue _value;
- std::optional<std::pair<AttrId, AttrValue>> cachedValue;
-
- AttrKey getKey();
-
- Value & getValue();
-
-public:
-
- AttrCursor(
- ref<EvalCache> root,
- Parent parent,
- Value * value = nullptr,
- std::optional<std::pair<AttrId, AttrValue>> && cachedValue = {});
-
- std::vector<Symbol> getAttrPath() const;
-
- std::vector<Symbol> getAttrPath(Symbol name) const;
-
- std::string getAttrPathStr() const;
-
- std::string getAttrPathStr(Symbol name) const;
-
- std::shared_ptr<AttrCursor> maybeGetAttr(Symbol name);
-
- std::shared_ptr<AttrCursor> maybeGetAttr(std::string_view name);
-
- std::shared_ptr<AttrCursor> getAttr(Symbol name);
-
- std::shared_ptr<AttrCursor> getAttr(std::string_view name);
-
- std::shared_ptr<AttrCursor> findAlongAttrPath(const std::vector<Symbol> & attrPath);
-
- std::string getString();
-
- std::vector<Symbol> getAttrs();
-
- bool isDerivation();
-
- Value & forceValue();
-};
-
-}