diff options
author | Eelco Dolstra <edolstra@gmail.com> | 2020-04-20 13:14:59 +0200 |
---|---|---|
committer | Eelco Dolstra <edolstra@gmail.com> | 2020-04-20 13:14:59 +0200 |
commit | 42a12f9232c8e3373df7f4660b2dfd837db92e4b (patch) | |
tree | 6756ed86b59fb603d68742076c2405f77887073e /src/libexpr/flake | |
parent | 539a9c1c5f0e4c9ab2262e7cf48460e02b8b0e12 (diff) |
Move eval-cache.{cc,hh}
Diffstat (limited to 'src/libexpr/flake')
-rw-r--r-- | src/libexpr/flake/eval-cache.cc | 460 | ||||
-rw-r--r-- | src/libexpr/flake/eval-cache.hh | 103 |
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(); -}; - -} |