123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385 |
- #pragma once
- #include "hash.hh"
- #include "serialise.hh"
- #include <string>
- #include <map>
- #include <memory>
- namespace nix {
- typedef std::map<Path, Path> Roots;
- struct GCOptions
- {
- /* Garbage collector operation:
- - `gcReturnLive': return the set of paths reachable from
- (i.e. in the closure of) the roots.
- - `gcReturnDead': return the set of paths not reachable from
- the roots.
- - `gcDeleteDead': actually delete the latter set.
- - `gcDeleteSpecific': delete the paths listed in
- `pathsToDelete', insofar as they are not reachable.
- */
- typedef enum {
- gcReturnLive,
- gcReturnDead,
- gcDeleteDead,
- gcDeleteSpecific,
- } GCAction;
- GCAction action;
- /* If `ignoreLiveness' is set, then reachability from the roots is
- ignored (dangerous!). However, the paths must still be
- unreferenced *within* the store (i.e., there can be no other
- store paths that depend on them). */
- bool ignoreLiveness;
- /* For `gcDeleteSpecific', the paths to delete. */
- PathSet pathsToDelete;
- /* Stop after at least `maxFreed' bytes have been freed. */
- unsigned long long maxFreed;
- GCOptions();
- };
- struct GCResults
- {
- /* Depending on the action, the GC roots, or the paths that would
- be or have been deleted. */
- PathSet paths;
- /* For `gcReturnDead', `gcDeleteDead' and `gcDeleteSpecific', the
- number of bytes that would be or was freed. */
- unsigned long long bytesFreed;
- GCResults()
- {
- bytesFreed = 0;
- }
- };
- struct SubstitutablePathInfo
- {
- Path deriver;
- PathSet references;
- unsigned long long downloadSize; /* 0 = unknown or inapplicable */
- unsigned long long narSize; /* 0 = unknown */
- };
- typedef std::map<Path, SubstitutablePathInfo> SubstitutablePathInfos;
- struct ValidPathInfo
- {
- Path path;
- Path deriver;
- Hash hash;
- PathSet references;
- time_t registrationTime = 0;
- uint64_t narSize = 0; // 0 = unknown
- uint64_t id; // internal use only
- bool operator == (const ValidPathInfo & i) const
- {
- return
- path == i.path
- && hash == i.hash
- && references == i.references;
- }
- };
- typedef list<ValidPathInfo> ValidPathInfos;
- enum BuildMode { bmNormal, bmRepair, bmCheck };
- struct BuildResult
- {
- enum Status {
- Built = 0,
- Substituted,
- AlreadyValid,
- PermanentFailure,
- InputRejected,
- OutputRejected,
- TransientFailure, // possibly transient
- CachedFailure,
- TimedOut,
- MiscFailure,
- DependencyFailed,
- LogLimitExceeded,
- NotDeterministic,
- } status = MiscFailure;
- std::string errorMsg;
- //time_t startTime = 0, stopTime = 0;
- bool success() {
- return status == Built || status == Substituted || status == AlreadyValid;
- }
- };
- class StoreAPI
- {
- public:
- virtual ~StoreAPI() { }
- /* Check whether a path is valid. */
- virtual bool isValidPath(const Path & path) = 0;
- /* Query which of the given paths is valid. */
- virtual PathSet queryValidPaths(const PathSet & paths) = 0;
- /* Query the set of all valid paths. */
- virtual PathSet queryAllValidPaths() = 0;
- /* Query information about a valid path. */
- virtual ValidPathInfo queryPathInfo(const Path & path) = 0;
- /* Query the hash of a valid path. */
- virtual Hash queryPathHash(const Path & path) = 0;
- /* Query the set of outgoing FS references for a store path. The
- result is not cleared. */
- virtual void queryReferences(const Path & path,
- PathSet & references) = 0;
- /* Queries the set of incoming FS references for a store path.
- The result is not cleared. */
- virtual void queryReferrers(const Path & path,
- PathSet & referrers) = 0;
- /* Query the deriver of a store path. Return the empty string if
- no deriver has been set. */
- virtual Path queryDeriver(const Path & path) = 0;
- /* Return all currently valid derivations that have `path' as an
- output. (Note that the result of `queryDeriver()' is the
- derivation that was actually used to produce `path', which may
- not exist anymore.) */
- virtual PathSet queryValidDerivers(const Path & path) = 0;
- /* Query the outputs of the derivation denoted by `path'. */
- virtual PathSet queryDerivationOutputs(const Path & path) = 0;
- /* Query the output names of the derivation denoted by `path'. */
- virtual StringSet queryDerivationOutputNames(const Path & path) = 0;
- /* Query the full store path given the hash part of a valid store
- path, or "" if the path doesn't exist. */
- virtual Path queryPathFromHashPart(const string & hashPart) = 0;
- /* Query which of the given paths have substitutes. */
- virtual PathSet querySubstitutablePaths(const PathSet & paths) = 0;
- /* Query substitute info (i.e. references, derivers and download
- sizes) of a set of paths. If a path does not have substitute
- info, it's omitted from the resulting ‘infos’ map. */
- virtual void querySubstitutablePathInfos(const PathSet & paths,
- SubstitutablePathInfos & infos) = 0;
- /* Copy the contents of a path to the store and register the
- validity the resulting path. The resulting path is returned.
- The function object `filter' can be used to exclude files (see
- libutil/archive.hh). */
- virtual Path addToStore(const string & name, const Path & srcPath,
- bool recursive = true, HashType hashAlgo = htSHA256,
- PathFilter & filter = defaultPathFilter, bool repair = false) = 0;
- /* Like addToStore, but the contents written to the output path is
- a regular file containing the given string. */
- virtual Path addTextToStore(const string & name, const string & s,
- const PathSet & references, bool repair = false) = 0;
- /* Export a store path, that is, create a NAR dump of the store
- path and append its references and its deriver. Optionally, a
- cryptographic signature (created by OpenSSL) of the preceding
- data is attached. */
- virtual void exportPath(const Path & path, bool sign,
- Sink & sink) = 0;
- /* Import a sequence of NAR dumps created by exportPaths() into
- the Nix store. */
- virtual Paths importPaths(bool requireSignature, Source & source) = 0;
- /* For each path, if it's a derivation, build it. Building a
- derivation means ensuring that the output paths are valid. If
- they are already valid, this is a no-op. Otherwise, validity
- can be reached in two ways. First, if the output paths is
- substitutable, then build the path that way. Second, the
- output paths can be created by running the builder, after
- recursively building any sub-derivations. For inputs that are
- not derivations, substitute them. */
- virtual void buildPaths(const PathSet & paths, BuildMode buildMode = bmNormal) = 0;
- /* Ensure that a path is valid. If it is not currently valid, it
- may be made valid by running a substitute (if defined for the
- path). */
- virtual void ensurePath(const Path & path) = 0;
- /* Add a store path as a temporary root of the garbage collector.
- The root disappears as soon as we exit. */
- virtual void addTempRoot(const Path & path) = 0;
- /* Add an indirect root, which is merely a symlink to `path' from
- /nix/var/nix/gcroots/auto/<hash of `path'>. `path' is supposed
- to be a symlink to a store path. The garbage collector will
- automatically remove the indirect root when it finds that
- `path' has disappeared. */
- virtual void addIndirectRoot(const Path & path) = 0;
- /* Acquire the global GC lock, then immediately release it. This
- function must be called after registering a new permanent root,
- but before exiting. Otherwise, it is possible that a running
- garbage collector doesn't see the new root and deletes the
- stuff we've just built. By acquiring the lock briefly, we
- ensure that either:
- - The collector is already running, and so we block until the
- collector is finished. The collector will know about our
- *temporary* locks, which should include whatever it is we
- want to register as a permanent lock.
- - The collector isn't running, or it's just started but hasn't
- acquired the GC lock yet. In that case we get and release
- the lock right away, then exit. The collector scans the
- permanent root and sees our's.
- In either case the permanent root is seen by the collector. */
- virtual void syncWithGC() = 0;
- /* Find the roots of the garbage collector. Each root is a pair
- (link, storepath) where `link' is the path of the symlink
- outside of the Nix store that point to `storePath'. */
- virtual Roots findRoots() = 0;
- /* Perform a garbage collection. */
- virtual void collectGarbage(const GCOptions & options, GCResults & results) = 0;
- /* Return the set of paths that have failed to build.*/
- virtual PathSet queryFailedPaths() = 0;
- /* Clear the "failed" status of the given paths. The special
- value `*' causes all failed paths to be cleared. */
- virtual void clearFailedPaths(const PathSet & paths) = 0;
- /* Return a string representing information about the path that
- can be loaded into the database using `nix-store --load-db' or
- `nix-store --register-validity'. */
- string makeValidityRegistration(const PathSet & paths,
- bool showDerivers, bool showHash);
- /* Optimise the disk space usage of the Nix store by hard-linking files
- with the same contents. */
- virtual void optimiseStore() = 0;
- /* Check the integrity of the Nix store. Returns true if errors
- remain. */
- virtual bool verifyStore(bool checkContents, bool repair) = 0;
- };
- /* !!! These should be part of the store API, I guess. */
- /* Throw an exception if `path' is not directly in the Nix store. */
- void assertStorePath(const Path & path);
- bool isInStore(const Path & path);
- bool isStorePath(const Path & path);
- /* Extract the name part of the given store path. */
- string storePathToName(const Path & path);
- void checkStoreName(const string & name);
- /* Chop off the parts after the top-level store name, e.g.,
- /nix/store/abcd-foo/bar => /nix/store/abcd-foo. */
- Path toStorePath(const Path & path);
- /* Constructs a unique store path name. */
- Path makeStorePath(const string & type,
- const Hash & hash, const string & name);
- Path makeOutputPath(const string & id,
- const Hash & hash, const string & name);
- Path makeFixedOutputPath(bool recursive,
- HashType hashAlgo, Hash hash, string name);
- /* Preparatory part of addTextToStore().
- !!! Computation of the path should take the references given to
- addTextToStore() into account, otherwise we have a (relatively
- minor) security hole: a caller can register a source file with
- bogus references. If there are too many references, the path may
- not be garbage collected when it has to be (not really a problem,
- the caller could create a root anyway), or it may be garbage
- collected when it shouldn't be (more serious).
- Hashing the references would solve this (bogus references would
- simply yield a different store path, so other users wouldn't be
- affected), but it has some backwards compatibility issues (the
- hashing scheme changes), so I'm not doing that for now. */
- Path computeStorePathForText(const string & name, const string & s,
- const PathSet & references);
- /* Remove the temporary roots file for this process. Any temporary
- root becomes garbage after this point unless it has been registered
- as a (permanent) root. */
- void removeTempRoots();
- /* Register a permanent GC root. */
- Path addPermRoot(StoreAPI & store, const Path & storePath,
- const Path & gcRoot, bool indirect, bool allowOutsideRootsDir = false);
- /* Sort a set of paths topologically under the references relation.
- If p refers to q, then p preceeds q in this list. */
- Paths topoSortPaths(StoreAPI & store, const PathSet & paths);
- /* For now, there is a single global store API object, but we'll
- purify that in the future. */
- extern std::shared_ptr<StoreAPI> store;
- /* Factory method: open the Nix database, either through the local or
- remote implementation. */
- std::shared_ptr<StoreAPI> openStore(bool reserveSpace = true);
- /* Display a set of paths in human-readable form (i.e., between quotes
- and separated by commas). */
- string showPaths(const PathSet & paths);
- /* Export multiple paths in the format expected by ‘nix-store
- --import’. */
- void exportPaths(StoreAPI & store, const Paths & paths,
- bool sign, Sink & sink);
- MakeError(SubstError, Error)
- MakeError(BuildError, Error) /* denotes a permanent build failure */
- }
|