LLVM 23.0.0git
OnDiskCAS.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "BuiltinCAS.h"
16#include "llvm/Support/Error.h"
17
18using namespace llvm;
19using namespace llvm::cas;
20using namespace llvm::cas::builtin;
21
22namespace {
23
24class OnDiskCAS : public BuiltinCAS {
25public:
26 Expected<ObjectRef> storeImpl(ArrayRef<uint8_t> ComputedHash,
28 ArrayRef<char> Data) final;
29
30 Expected<std::optional<ObjectHandle>> loadIfExists(ObjectRef Ref) final;
31
32 CASID getID(ObjectRef Ref) const final;
33
34 std::optional<ObjectRef> getReference(const CASID &ID) const final;
35
36 Expected<bool> isMaterialized(ObjectRef Ref) const final;
37
38 ArrayRef<char> getDataConst(ObjectHandle Node) const final;
39
40 void print(raw_ostream &OS) const final;
41 Error validate(bool CheckHash) const final;
42
43 static Expected<std::unique_ptr<OnDiskCAS>> open(StringRef Path);
44
45 OnDiskCAS(std::shared_ptr<ondisk::UnifiedOnDiskCache> UniDB)
46 : UnifiedDB(std::move(UniDB)), DB(&UnifiedDB->getGraphDB()) {}
47
48private:
49 ObjectHandle convertHandle(ondisk::ObjectHandle Node) const {
50 return makeObjectHandle(Node.getOpaqueData());
51 }
52
53 ondisk::ObjectHandle convertHandle(ObjectHandle Node) const {
54 return ondisk::ObjectHandle(Node.getInternalRef(*this));
55 }
56
57 ObjectRef convertRef(ondisk::ObjectID Ref) const {
58 return makeObjectRef(Ref.getOpaqueData());
59 }
60
61 ondisk::ObjectID convertRef(ObjectRef Ref) const {
62 return ondisk::ObjectID::fromOpaqueData(Ref.getInternalRef(*this));
63 }
64
65 size_t getNumRefs(ObjectHandle Node) const final {
66 auto RefsRange = DB->getObjectRefs(convertHandle(Node));
67 return llvm::size(RefsRange);
68 }
69
70 ObjectRef readRef(ObjectHandle Node, size_t I) const final {
71 auto RefsRange = DB->getObjectRefs(convertHandle(Node));
72 return convertRef(RefsRange.begin()[I]);
73 }
74
75 Error forEachRef(ObjectHandle Node,
76 function_ref<Error(ObjectRef)> Callback) const final;
77
78 Error setSizeLimit(std::optional<uint64_t> SizeLimit) final;
79 Expected<std::optional<uint64_t>> getStorageSize() const final;
80 Error pruneStorageData() final;
81
82 OnDiskCAS(std::unique_ptr<ondisk::OnDiskGraphDB> GraphDB)
83 : OwnedDB(std::move(GraphDB)), DB(OwnedDB.get()) {}
84
85 std::unique_ptr<ondisk::OnDiskGraphDB> OwnedDB;
86 std::shared_ptr<ondisk::UnifiedOnDiskCache> UnifiedDB;
87 ondisk::OnDiskGraphDB *DB;
88};
89
90} // end anonymous namespace
91
92void OnDiskCAS::print(raw_ostream &OS) const { DB->print(OS); }
93Error OnDiskCAS::validate(bool CheckHash) const {
94 auto Hasher = [](ArrayRef<ArrayRef<uint8_t>> Refs, ArrayRef<char> Data,
95 SmallVectorImpl<uint8_t> &Result) {
97 Refs, Data);
98 Result.assign(Hash.begin(), Hash.end());
99 };
100
101 if (auto E = DB->validate(CheckHash, Hasher))
102 return E;
103
104 return Error::success();
105}
106
107CASID OnDiskCAS::getID(ObjectRef Ref) const {
108 ArrayRef<uint8_t> Hash = DB->getDigest(convertRef(Ref));
109 return CASID::create(&getContext(), toStringRef(Hash));
110}
111
112std::optional<ObjectRef> OnDiskCAS::getReference(const CASID &ID) const {
113 std::optional<ondisk::ObjectID> ObjID =
114 DB->getExistingReference(ID.getHash());
115 if (!ObjID)
116 return std::nullopt;
117 return convertRef(*ObjID);
118}
119
120Expected<bool> OnDiskCAS::isMaterialized(ObjectRef ExternalRef) const {
121 return DB->isMaterialized(convertRef(ExternalRef));
122}
123
124ArrayRef<char> OnDiskCAS::getDataConst(ObjectHandle Node) const {
125 return DB->getObjectData(convertHandle(Node));
126}
127
128Expected<std::optional<ObjectHandle>>
129OnDiskCAS::loadIfExists(ObjectRef ExternalRef) {
130 Expected<std::optional<ondisk::ObjectHandle>> ObjHnd =
131 DB->load(convertRef(ExternalRef));
132 if (!ObjHnd)
133 return ObjHnd.takeError();
134 if (!*ObjHnd)
135 return std::nullopt;
136 return convertHandle(**ObjHnd);
137}
138
139Expected<ObjectRef> OnDiskCAS::storeImpl(ArrayRef<uint8_t> ComputedHash,
141 ArrayRef<char> Data) {
143 IDs.reserve(Refs.size());
144 for (ObjectRef Ref : Refs) {
145 IDs.push_back(convertRef(Ref));
146 }
147
148 auto StoredID = DB->getReference(ComputedHash);
149 if (LLVM_UNLIKELY(!StoredID))
150 return StoredID.takeError();
151 if (Error E = DB->store(*StoredID, IDs, Data))
152 return std::move(E);
153 return convertRef(*StoredID);
154}
155
156Error OnDiskCAS::forEachRef(ObjectHandle Node,
157 function_ref<Error(ObjectRef)> Callback) const {
158 auto RefsRange = DB->getObjectRefs(convertHandle(Node));
159 for (ondisk::ObjectID Ref : RefsRange) {
160 if (Error E = Callback(convertRef(Ref)))
161 return E;
162 }
163 return Error::success();
164}
165
166Error OnDiskCAS::setSizeLimit(std::optional<uint64_t> SizeLimit) {
167 UnifiedDB->setSizeLimit(SizeLimit);
168 return Error::success();
169}
170
171Expected<std::optional<uint64_t>> OnDiskCAS::getStorageSize() const {
172 return UnifiedDB->getStorageSize();
173}
174
175Error OnDiskCAS::pruneStorageData() { return UnifiedDB->collectGarbage(); }
176
177Expected<std::unique_ptr<OnDiskCAS>> OnDiskCAS::open(StringRef AbsPath) {
178 std::shared_ptr<ondisk::OnDiskCASLogger> Logger;
179#ifndef _WIN32
180 if (Error E =
181 ondisk::OnDiskCASLogger::openIfEnabled(AbsPath).moveInto(Logger))
182 return std::move(E);
183#endif
184
185 Expected<std::unique_ptr<ondisk::OnDiskGraphDB>> DB =
187 sizeof(HashType), /*UpstreamDB=*/nullptr,
188 std::move(Logger));
189 if (!DB)
190 return DB.takeError();
191 return std::unique_ptr<OnDiskCAS>(new OnDiskCAS(std::move(*DB)));
192}
193
195#if LLVM_ENABLE_ONDISK_CAS
196 return true;
197#else
198 return false;
199#endif
200}
201
203#if LLVM_ENABLE_ONDISK_CAS
204 // FIXME: An absolute path isn't really good enough. Should open a directory
205 // and use openat() for files underneath.
206 SmallString<256> AbsPath;
207 Path.toVector(AbsPath);
208 sys::fs::make_absolute(AbsPath);
209
210 return OnDiskCAS::open(AbsPath);
211#else
212 return createStringError(inconvertibleErrorCode(), "OnDiskCAS is disabled");
213#endif /* LLVM_ENABLE_ONDISK_CAS */
214}
215
216std::unique_ptr<ObjectStore>
218 std::shared_ptr<ondisk::UnifiedOnDiskCache> UniDB) {
219 return std::make_unique<OnDiskCAS>(std::move(UniDB));
220}
aarch64 promote const
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_UNLIKELY(EXPR)
Definition Compiler.h:336
static cl::opt< unsigned > SizeLimit("eif-limit", cl::init(6), cl::Hidden, cl::desc("Size limit in Hexagon early if-conversion"))
#define I(x, y, z)
Definition MD5.cpp:57
This file declares interface for OnDiskCASLogger, an interface that can be used to log CAS events to ...
This declares OnDiskGraphDB, an ondisk CAS database with a fixed length hash.
size_t size() const
size - Get the array size.
Definition ArrayRef.h:142
static ErrorSuccess success()
Create a success value.
Definition Error.h:336
Tagged union holding either a T or a Error.
Definition Error.h:485
Error takeError()
Take ownership of the stored error.
Definition Error.h:612
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition SmallString.h:26
void reserve(size_type N)
void push_back(const T &Elt)
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
static HashT hashObject(const ObjectStore &CAS, ArrayRef< ObjectRef > Refs, ArrayRef< char > Data)
static CASID create(const CASContext *Context, StringRef Hash)
Create CASID from CASContext and raw hash bytes.
Definition CASID.h:116
static StringRef getHashName()
Get the name of the hash for any table identifiers.
Common base class for builtin CAS implementations using the same CASContext.
Definition BuiltinCAS.h:24
static ObjectID fromOpaqueData(uint64_t Opaque)
static LLVM_ABI Expected< std::unique_ptr< OnDiskCASLogger > > openIfEnabled(const Twine &Path)
Create or append to a log file inside the given CAS directory Path if logging is enabled by the envir...
void print(raw_ostream &OS) const
LLVM_ABI_FOR_TEST Expected< std::optional< ObjectHandle > > load(ObjectID Ref)
Expected< bool > isMaterialized(ObjectID Ref)
Check whether the object associated with Ref is stored in the CAS.
Error validate(bool Deep, HashingFuncT Hasher) const
Validate the OnDiskGraphDB.
object_refs_range getObjectRefs(ObjectHandle Node) const
LLVM_ABI_FOR_TEST Error store(ObjectID ID, ArrayRef< ObjectID > Refs, ArrayRef< char > Data)
Associate data & references with a particular object ID.
ArrayRef< uint8_t > getDigest(ObjectID Ref) const
static LLVM_ABI_FOR_TEST Expected< std::unique_ptr< OnDiskGraphDB > > open(StringRef Path, StringRef HashName, unsigned HashByteSize, OnDiskGraphDB *UpstreamDB=nullptr, std::shared_ptr< OnDiskCASLogger > Logger=nullptr, FaultInPolicy Policy=FaultInPolicy::FullTree)
Open the on-disk store from a directory.
LLVM_ABI_FOR_TEST Expected< ObjectID > getReference(ArrayRef< uint8_t > Hash)
Form a reference for the provided hash.
LLVM_ABI_FOR_TEST ArrayRef< char > getObjectData(ObjectHandle Node) const
LLVM_ABI_FOR_TEST std::optional< ObjectID > getExistingReference(ArrayRef< uint8_t > Digest, bool CheckUpstream=true)
Get an existing reference to the object Digest.
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
void validate(const Triple &TT, const FeatureBitset &FeatureBits)
std::unique_ptr< ObjectStore > createObjectStoreFromUnifiedOnDiskCache(std::shared_ptr< ondisk::UnifiedOnDiskCache > UniDB)
decltype(HasherT::hash(std::declval< ArrayRef< uint8_t > & >())) HashType
bool isOnDiskCASEnabled()
LLVM_ABI Expected< std::unique_ptr< ObjectStore > > createOnDiskCAS(const Twine &Path)
Create a persistent on-disk path at Path.
llvm::unique_function< void(llvm::Expected< T >)> Callback
A Callback<T> is a void function that accepts Expected<T>.
Definition Transport.h:139
NodeAddr< NodeBase * > Node
Definition RDFGraph.h:381
Context & getContext() const
Definition BasicBlock.h:99
LLVM_ABI std::error_code make_absolute(SmallVectorImpl< char > &path)
Make path an absolute path.
Definition Path.cpp:962
This is an optimization pass for GlobalISel generic memory operations.
Definition Types.h:26
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
Definition STLExtras.h:1667
LLVM_ABI std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Definition Error.cpp:94
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition Error.h:1305
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
@ Ref
The access may reference the value stored in memory.
Definition ModRef.h:32
FunctionAddr VTableAddr uintptr_t uintptr_t Data
Definition InstrProf.h:189
ArrayRef(const T &OneElt) -> ArrayRef< T >
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1915
StringRef toStringRef(bool B)
Construct a string ref from a boolean.