LLVM 22.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"
15#include "llvm/Support/Error.h"
16
17using namespace llvm;
18using namespace llvm::cas;
19using namespace llvm::cas::builtin;
20
21namespace {
22
23class OnDiskCAS : public BuiltinCAS {
24public:
25 Expected<ObjectRef> storeImpl(ArrayRef<uint8_t> ComputedHash,
27 ArrayRef<char> Data) final;
28
29 Expected<std::optional<ObjectHandle>> loadIfExists(ObjectRef Ref) final;
30
31 CASID getID(ObjectRef Ref) const final;
32
33 std::optional<ObjectRef> getReference(const CASID &ID) const final;
34
35 Expected<bool> isMaterialized(ObjectRef Ref) const final;
36
37 ArrayRef<char> getDataConst(ObjectHandle Node) const final;
38
39 void print(raw_ostream &OS) const final;
40 Error validate(bool CheckHash) const final;
41
42 static Expected<std::unique_ptr<OnDiskCAS>> open(StringRef Path);
43
44 OnDiskCAS(std::shared_ptr<ondisk::UnifiedOnDiskCache> UniDB)
45 : UnifiedDB(std::move(UniDB)), DB(&UnifiedDB->getGraphDB()) {}
46
47private:
48 ObjectHandle convertHandle(ondisk::ObjectHandle Node) const {
49 return makeObjectHandle(Node.getOpaqueData());
50 }
51
52 ondisk::ObjectHandle convertHandle(ObjectHandle Node) const {
53 return ondisk::ObjectHandle(Node.getInternalRef(*this));
54 }
55
56 ObjectRef convertRef(ondisk::ObjectID Ref) const {
57 return makeObjectRef(Ref.getOpaqueData());
58 }
59
60 ondisk::ObjectID convertRef(ObjectRef Ref) const {
61 return ondisk::ObjectID::fromOpaqueData(Ref.getInternalRef(*this));
62 }
63
64 size_t getNumRefs(ObjectHandle Node) const final {
65 auto RefsRange = DB->getObjectRefs(convertHandle(Node));
66 return std::distance(RefsRange.begin(), RefsRange.end());
67 }
68
69 ObjectRef readRef(ObjectHandle Node, size_t I) const final {
70 auto RefsRange = DB->getObjectRefs(convertHandle(Node));
71 return convertRef(RefsRange.begin()[I]);
72 }
73
74 Error forEachRef(ObjectHandle Node,
75 function_ref<Error(ObjectRef)> Callback) const final;
76
77 Error setSizeLimit(std::optional<uint64_t> SizeLimit) final;
78 Expected<std::optional<uint64_t>> getStorageSize() const final;
79 Error pruneStorageData() final;
80
81 OnDiskCAS(std::unique_ptr<ondisk::OnDiskGraphDB> GraphDB)
82 : OwnedDB(std::move(GraphDB)), DB(OwnedDB.get()) {}
83
84 std::unique_ptr<ondisk::OnDiskGraphDB> OwnedDB;
85 std::shared_ptr<ondisk::UnifiedOnDiskCache> UnifiedDB;
86 ondisk::OnDiskGraphDB *DB;
87};
88
89} // end anonymous namespace
90
91void OnDiskCAS::print(raw_ostream &OS) const { DB->print(OS); }
92Error OnDiskCAS::validate(bool CheckHash) const {
93 auto Hasher = [](ArrayRef<ArrayRef<uint8_t>> Refs, ArrayRef<char> Data,
94 SmallVectorImpl<uint8_t> &Result) {
96 Refs, Data);
97 Result.assign(Hash.begin(), Hash.end());
98 };
99
100 if (auto E = DB->validate(CheckHash, Hasher))
101 return E;
102
103 return Error::success();
104}
105
106CASID OnDiskCAS::getID(ObjectRef Ref) const {
107 ArrayRef<uint8_t> Hash = DB->getDigest(convertRef(Ref));
108 return CASID::create(&getContext(), toStringRef(Hash));
109}
110
111std::optional<ObjectRef> OnDiskCAS::getReference(const CASID &ID) const {
112 std::optional<ondisk::ObjectID> ObjID =
113 DB->getExistingReference(ID.getHash());
114 if (!ObjID)
115 return std::nullopt;
116 return convertRef(*ObjID);
117}
118
119Expected<bool> OnDiskCAS::isMaterialized(ObjectRef ExternalRef) const {
120 return DB->isMaterialized(convertRef(ExternalRef));
121}
122
123ArrayRef<char> OnDiskCAS::getDataConst(ObjectHandle Node) const {
124 return DB->getObjectData(convertHandle(Node));
125}
126
127Expected<std::optional<ObjectHandle>>
128OnDiskCAS::loadIfExists(ObjectRef ExternalRef) {
129 Expected<std::optional<ondisk::ObjectHandle>> ObjHnd =
130 DB->load(convertRef(ExternalRef));
131 if (!ObjHnd)
132 return ObjHnd.takeError();
133 if (!*ObjHnd)
134 return std::nullopt;
135 return convertHandle(**ObjHnd);
136}
137
138Expected<ObjectRef> OnDiskCAS::storeImpl(ArrayRef<uint8_t> ComputedHash,
140 ArrayRef<char> Data) {
142 IDs.reserve(Refs.size());
143 for (ObjectRef Ref : Refs) {
144 IDs.push_back(convertRef(Ref));
145 }
146
147 auto StoredID = DB->getReference(ComputedHash);
148 if (LLVM_UNLIKELY(!StoredID))
149 return StoredID.takeError();
150 if (Error E = DB->store(*StoredID, IDs, Data))
151 return std::move(E);
152 return convertRef(*StoredID);
153}
154
155Error OnDiskCAS::forEachRef(ObjectHandle Node,
156 function_ref<Error(ObjectRef)> Callback) const {
157 auto RefsRange = DB->getObjectRefs(convertHandle(Node));
158 for (ondisk::ObjectID Ref : RefsRange) {
159 if (Error E = Callback(convertRef(Ref)))
160 return E;
161 }
162 return Error::success();
163}
164
165Error OnDiskCAS::setSizeLimit(std::optional<uint64_t> SizeLimit) {
166 UnifiedDB->setSizeLimit(SizeLimit);
167 return Error::success();
168}
169
170Expected<std::optional<uint64_t>> OnDiskCAS::getStorageSize() const {
171 return UnifiedDB->getStorageSize();
172}
173
174Error OnDiskCAS::pruneStorageData() { return UnifiedDB->collectGarbage(); }
175
176Expected<std::unique_ptr<OnDiskCAS>> OnDiskCAS::open(StringRef AbsPath) {
177 Expected<std::unique_ptr<ondisk::OnDiskGraphDB>> DB =
179 sizeof(HashType));
180 if (!DB)
181 return DB.takeError();
182 return std::unique_ptr<OnDiskCAS>(new OnDiskCAS(std::move(*DB)));
183}
184
186#if LLVM_ENABLE_ONDISK_CAS
187 return true;
188#else
189 return false;
190#endif
191}
192
194#if LLVM_ENABLE_ONDISK_CAS
195 // FIXME: An absolute path isn't really good enough. Should open a directory
196 // and use openat() for files underneath.
197 SmallString<256> AbsPath;
198 Path.toVector(AbsPath);
199 sys::fs::make_absolute(AbsPath);
200
201 return OnDiskCAS::open(AbsPath);
202#else
203 return createStringError(inconvertibleErrorCode(), "OnDiskCAS is disabled");
204#endif /* LLVM_ENABLE_ONDISK_CAS */
205}
206
207std::unique_ptr<ObjectStore>
209 std::shared_ptr<ondisk::UnifiedOnDiskCache> UniDB) {
210 return std::make_unique<OnDiskCAS>(std::move(UniDB));
211}
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:58
This declares OnDiskGraphDB, an ondisk CAS database with a fixed length hash.
size_t size() const
size - Get the array size.
Definition ArrayRef.h:143
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)
void print(raw_ostream &OS) const
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
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 Expected< std::unique_ptr< OnDiskGraphDB > > open(StringRef Path, StringRef HashName, unsigned HashByteSize, OnDiskGraphDB *UpstreamDB=nullptr, FaultInPolicy Policy=FaultInPolicy::FullTree)
Open the on-disk store from a directory.
std::optional< ObjectID > getExistingReference(ArrayRef< uint8_t > Digest)
Get an existing reference to the object Digest.
Expected< ObjectID > getReference(ArrayRef< uint8_t > Hash)
Form a reference for the provided hash.
ArrayRef< char > getObjectData(ObjectHandle Node) const
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()
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:136
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:955
This is an optimization pass for GlobalISel generic memory operations.
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)
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:98
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:1867
StringRef toStringRef(bool B)
Construct a string ref from a boolean.