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"
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 llvm::size(RefsRange);
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 if (auto E = DB->validate(CheckHash, builtin::hashingFunc))
94 return E;
95
96 return Error::success();
97}
98
99CASID OnDiskCAS::getID(ObjectRef Ref) const {
100 ArrayRef<uint8_t> Hash = DB->getDigest(convertRef(Ref));
101 return CASID::create(&getContext(), toStringRef(Hash));
102}
103
104std::optional<ObjectRef> OnDiskCAS::getReference(const CASID &ID) const {
105 std::optional<ondisk::ObjectID> ObjID =
106 DB->getExistingReference(ID.getHash());
107 if (!ObjID)
108 return std::nullopt;
109 return convertRef(*ObjID);
110}
111
112Expected<bool> OnDiskCAS::isMaterialized(ObjectRef ExternalRef) const {
113 return DB->isMaterialized(convertRef(ExternalRef));
114}
115
116ArrayRef<char> OnDiskCAS::getDataConst(ObjectHandle Node) const {
117 return DB->getObjectData(convertHandle(Node));
118}
119
120Expected<std::optional<ObjectHandle>>
121OnDiskCAS::loadIfExists(ObjectRef ExternalRef) {
122 Expected<std::optional<ondisk::ObjectHandle>> ObjHnd =
123 DB->load(convertRef(ExternalRef));
124 if (!ObjHnd)
125 return ObjHnd.takeError();
126 if (!*ObjHnd)
127 return std::nullopt;
128 return convertHandle(**ObjHnd);
129}
130
131Expected<ObjectRef> OnDiskCAS::storeImpl(ArrayRef<uint8_t> ComputedHash,
133 ArrayRef<char> Data) {
135 IDs.reserve(Refs.size());
136 for (ObjectRef Ref : Refs) {
137 IDs.push_back(convertRef(Ref));
138 }
139
140 auto StoredID = DB->getReference(ComputedHash);
141 if (LLVM_UNLIKELY(!StoredID))
142 return StoredID.takeError();
143 if (Error E = DB->store(*StoredID, IDs, Data))
144 return std::move(E);
145 return convertRef(*StoredID);
146}
147
148Error OnDiskCAS::forEachRef(ObjectHandle Node,
149 function_ref<Error(ObjectRef)> Callback) const {
150 auto RefsRange = DB->getObjectRefs(convertHandle(Node));
151 for (ondisk::ObjectID Ref : RefsRange) {
152 if (Error E = Callback(convertRef(Ref)))
153 return E;
154 }
155 return Error::success();
156}
157
158Error OnDiskCAS::setSizeLimit(std::optional<uint64_t> SizeLimit) {
159 UnifiedDB->setSizeLimit(SizeLimit);
160 return Error::success();
161}
162
163Expected<std::optional<uint64_t>> OnDiskCAS::getStorageSize() const {
164 return UnifiedDB->getStorageSize();
165}
166
167Error OnDiskCAS::pruneStorageData() { return UnifiedDB->collectGarbage(); }
168
169Expected<std::unique_ptr<OnDiskCAS>> OnDiskCAS::open(StringRef AbsPath) {
170 std::shared_ptr<ondisk::OnDiskCASLogger> Logger;
171#ifndef _WIN32
172 if (Error E =
173 ondisk::OnDiskCASLogger::openIfEnabled(AbsPath).moveInto(Logger))
174 return std::move(E);
175#endif
176
177 Expected<std::unique_ptr<ondisk::OnDiskGraphDB>> DB =
179 sizeof(HashType), /*UpstreamDB=*/nullptr,
180 std::move(Logger));
181 if (!DB)
182 return DB.takeError();
183 return std::unique_ptr<OnDiskCAS>(new OnDiskCAS(std::move(*DB)));
184}
185
187#if LLVM_ENABLE_ONDISK_CAS
188 return true;
189#else
190 return false;
191#endif
192}
193
195#if LLVM_ENABLE_ONDISK_CAS
196 // FIXME: An absolute path isn't really good enough. Should open a directory
197 // and use openat() for files underneath.
198 SmallString<256> AbsPath;
199 Path.toVector(AbsPath);
200 sys::fs::make_absolute(AbsPath);
201
202 return OnDiskCAS::open(AbsPath);
203#else
204 return createStringError(inconvertibleErrorCode(), "OnDiskCAS is disabled");
205#endif /* LLVM_ENABLE_ONDISK_CAS */
206}
207
208std::unique_ptr<ObjectStore>
210 std::shared_ptr<ondisk::UnifiedOnDiskCache> UniDB) {
211 return std::make_unique<OnDiskCAS>(std::move(UniDB));
212}
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 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)
void hashingFunc(ArrayRef< ArrayRef< uint8_t > > Refs, ArrayRef< char > Data, SmallVectorImpl< uint8_t > &Result)
Convenience wrapper for BuiltinObjectHasher.
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.