LLVM 24.0.0git
OnDiskGraphDB.h
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/// \file
10/// This declares OnDiskGraphDB, an ondisk CAS database with a fixed length
11/// hash. This is the class that implements the database storage scheme without
12/// exposing the hashing algorithm.
13//
14//===----------------------------------------------------------------------===//
15
16#ifndef LLVM_CAS_ONDISKGRAPHDB_H
17#define LLVM_CAS_ONDISKGRAPHDB_H
18
23#include <atomic>
24
25namespace llvm {
26class MemoryBuffer;
27} // namespace llvm
28
29namespace llvm::cas::ondisk {
30
31/// Standard 8 byte reference inside OnDiskGraphDB.
32class InternalRef {
33public:
34 FileOffset getFileOffset() const { return FileOffset(Data); }
35 uint64_t getRawData() const { return Data; }
36
37 static InternalRef getFromRawData(uint64_t Data) { return InternalRef(Data); }
38 static InternalRef getFromOffset(FileOffset Offset) {
39 return InternalRef(Offset.get());
40 }
41
42 friend bool operator==(InternalRef LHS, InternalRef RHS) {
43 return LHS.Data == RHS.Data;
44 }
45
46private:
48 InternalRef(uint64_t Data) : Data(Data) {}
50};
51
52/// Compact 4 byte reference inside OnDiskGraphDB for smaller references.
53class InternalRef4B {
54public:
55 FileOffset getFileOffset() const { return FileOffset(Data); }
56 uint32_t getRawData() const { return Data; }
57
58 /// Shrink to 4B reference.
59 static std::optional<InternalRef4B> tryToShrink(InternalRef Ref) {
60 uint64_t Offset = Ref.getRawData();
61 if (Offset > UINT32_MAX)
62 return std::nullopt;
63 return InternalRef4B(Offset);
64 }
65
66 operator InternalRef() const {
68 }
69
70private:
71 friend class InternalRef;
72 InternalRef4B(uint32_t Data) : Data(Data) {}
74};
75
76/// Array of internal node references.
78public:
79 size_t size() const { return Size; }
80 bool empty() const { return !Size; }
81
83 : public iterator_facade_base<iterator, std::random_access_iterator_tag,
84 const InternalRef> {
85 public:
86 bool operator==(const iterator &RHS) const { return I == RHS.I; }
89 return *Ref;
91 }
107 if (auto *Ref = dyn_cast<const InternalRef *>(I))
108 I = Ref + N;
109 else
111 return *this;
112 }
114 if (auto *Ref = dyn_cast<const InternalRef *>(I))
115 I = Ref - N;
116 else
118 return *this;
119 }
120 InternalRef operator[](ptrdiff_t N) const { return *(this->operator+(N)); }
121
122 iterator() = default;
123
124 uint64_t getOpaqueData() const { return uintptr_t(I.getOpaqueValue()); }
125
127 return iterator(
129 const InternalRef4B *>::getFromOpaqueValue((void *)
130 Opaque));
131 }
132
133 private:
135 explicit iterator(
137 : I(I) {}
139 };
140
141 bool operator==(const InternalRefArrayRef &RHS) const {
142 return size() == RHS.size() && std::equal(begin(), end(), RHS.begin());
143 }
144
145 iterator begin() const { return iterator(Begin); }
146 iterator end() const { return begin() + Size; }
147
148 /// Array accessor.
149 InternalRef operator[](ptrdiff_t N) const { return begin()[N]; }
150
151 bool is4B() const { return isa<const InternalRef4B *>(Begin); }
152 bool is8B() const { return isa<const InternalRef *>(Begin); }
153
155 if (is4B()) {
156 auto *B = cast<const InternalRef4B *>(Begin);
157 return ArrayRef((const uint8_t *)B, sizeof(InternalRef4B) * Size);
158 }
159 auto *B = cast<const InternalRef *>(Begin);
160 return ArrayRef((const uint8_t *)B, sizeof(InternalRef) * Size);
161 }
162
163 InternalRefArrayRef(std::nullopt_t = std::nullopt) {
164 // This is useful so that all the casts in the \p iterator functions can
165 // operate without needing to check for a null value.
166 static InternalRef PlaceHolder = InternalRef::getFromRawData(0);
167 Begin = &PlaceHolder;
168 }
169
171 : Begin(Refs.begin()), Size(Refs.size()) {}
172
174 : Begin(Refs.begin()), Size(Refs.size()) {}
175
176private:
178 size_t Size = 0;
179};
180
181/// Reference to a node. The node's data may not be stored in the database.
182/// An \p ObjectID instance can only be used with the \p OnDiskGraphDB instance
183/// it came from. \p ObjectIDs from different \p OnDiskGraphDB instances are not
184/// comparable.
185class ObjectID {
186public:
187 uint64_t getOpaqueData() const { return Opaque; }
188
189 static ObjectID fromOpaqueData(uint64_t Opaque) { return ObjectID(Opaque); }
190
191 friend bool operator==(const ObjectID &LHS, const ObjectID &RHS) {
192 return LHS.Opaque == RHS.Opaque;
193 }
194 friend bool operator!=(const ObjectID &LHS, const ObjectID &RHS) {
195 return !(LHS == RHS);
196 }
197
198private:
199 explicit ObjectID(uint64_t Opaque) : Opaque(Opaque) {}
200 uint64_t Opaque;
201};
202
203/// Handle for a loaded node object.
205public:
206 explicit ObjectHandle(uint64_t Opaque) : Opaque(Opaque) {}
207 uint64_t getOpaqueData() const { return Opaque; }
208
211
212 friend bool operator==(const ObjectHandle &LHS, const ObjectHandle &RHS) {
213 return LHS.Opaque == RHS.Opaque;
214 }
215 friend bool operator!=(const ObjectHandle &LHS, const ObjectHandle &RHS) {
216 return !(LHS == RHS);
217 }
218
219private:
220 uint64_t Opaque;
221};
222
223/// Iterator for ObjectID.
225 : public iterator_facade_base<object_refs_iterator,
226 std::random_access_iterator_tag, ObjectID> {
227public:
228 bool operator==(const object_refs_iterator &RHS) const { return I == RHS.I; }
230 return ObjectID::fromOpaqueData((*I).getRawData());
231 }
232 bool operator<(const object_refs_iterator &RHS) const { return I < RHS.I; }
234 return I - RHS.I;
235 }
237 I += N;
238 return *this;
239 }
241 I -= N;
242 return *this;
243 }
244 ObjectID operator[](ptrdiff_t N) const { return *(this->operator+(N)); }
245
248
249 uint64_t getOpaqueData() const { return I.getOpaqueData(); }
250
254
255private:
257};
258
260
261/// On-disk CAS nodes database, independent of a particular hashing algorithm.
262class OnDiskGraphDB {
263public:
264 /// Associate data & references with a particular object ID. If there is
265 /// already a record for this object the operation is a no-op. \param ID the
266 /// object ID to associate the data & references with. \param Refs references
267 /// \param Data data buffer.
270
271 /// Associates the data of a file with a particular object ID. If there is
272 /// already a record for this object the operation is a no-op.
273 ///
274 /// This is more than a convenience variant of \c store(), \c storeFile() can
275 /// perform optimizations that reduce I/O and disk space consumption.
276 ///
277 /// If there are any concurrent modifications to the file, the contents in the
278 /// CAS may be corrupt.
279 ///
280 /// \param ID the object ID to associate the data with.
281 /// \param FilePath the path of the file data.
283
284 /// \returns \p nullopt if the object associated with \p Ref does not exist.
286
287 /// \returns the hash bytes digest for the object reference.
289 // ObjectID should be valid to fetch Digest.
290 return cantFail(getDigest(getInternalRef(Ref)));
291 }
292
293 /// Form a reference for the provided hash. The reference can be used as part
294 /// of a CAS object even if it's not associated with an object yet.
296
297 /// Get an existing reference to the object \p Digest.
298 ///
299 /// Returns \p nullopt if the object is not stored in this CAS.
300 LLVM_ABI std::optional<ObjectID>
301 getExistingReference(ArrayRef<uint8_t> Digest, bool CheckUpstream = true);
302
303 /// Check whether the object associated with \p Ref is stored in the CAS.
304 /// Note that this function will fault-in according to the policy.
306
307 /// Check whether the object associated with \p Ref is stored in the CAS.
308 /// Note that this function does not fault-in.
309 bool containsObject(ObjectID Ref, bool CheckUpstream = true) const {
310 auto Presence = getObjectPresence(Ref, CheckUpstream);
311 if (!Presence) {
312 consumeError(Presence.takeError());
313 return false;
314 }
315 switch (*Presence) {
316 case ObjectPresence::Missing:
317 return false;
318 case ObjectPresence::InPrimaryDB:
319 return true;
320 case ObjectPresence::OnlyInUpstreamDB:
321 return true;
322 }
323 llvm_unreachable("Unknown ObjectPresence enum");
324 }
325
326 /// \returns the data part of the provided object handle.
328
329 /// \returns the object referenced by the provided object handle.
331 InternalRefArrayRef Refs = getInternalRefs(Node);
332 return make_range(Refs.begin(), Refs.end());
333 }
334
335 /// Encapsulates file info for an underlying object node.
337 /// The data of the object node.
339
340 struct FileInfoTy {
341 /// The file path of the object node.
342 std::string FilePath;
343 /// Whether the file of the object leaf node has an extra nul appended at
344 /// the end. If the file is copied the extra nul needs to be removed.
346 };
347 /// File information for the object, if available.
348 std::optional<FileInfoTy> FileInfo;
349 };
350
351 /// Provides access to the underlying file path, that represents an object
352 /// leaf node, when available.
353 ///
354 /// This enables reducing I/O and disk space consumption, i.e. instead of
355 /// loading the data in memory and then writing it to a file, the client could
356 /// clone the underlying file directly. The client *must not* write to or
357 /// delete the underlying file, the path is provided only for reading/copying.
360
361 /// Get a MemoryBuffer for \p Node's data that stays valid after this
362 /// database is destroyed.
363 ///
364 /// Objects stored in a file of their own are re-read from it rather than
365 /// copied out of this database's mapping, which lets the pages be shared and
366 /// reclaimed rather than charged to this process. The rest are copied. Never
367 /// returns \c nullptr.
368 LLVM_ABI std::unique_ptr<MemoryBuffer>
370 bool RequiresNullTerminator) const;
371
372 /// \returns Total size of stored objects.
373 ///
374 /// NOTE: There's a possibility that the returned size is not including a
375 /// large object if the process crashed right at the point of inserting it.
376 LLVM_ABI size_t getStorageSize() const;
377
378 /// \returns The precentage of space utilization of hard space limits.
379 ///
380 /// Return value is an integer between 0 and 100 for percentage.
382
383 LLVM_ABI void print(raw_ostream &OS) const;
384
385 /// Hashing function type for validation.
388
389 /// Validate the OnDiskGraphDB.
390 ///
391 /// \param Deep if true, rehash all the objects to ensure no data
392 /// corruption in stored objects, otherwise just validate the structure of
393 /// CAS database.
394 /// \param Hasher is the hashing function used for objects inside CAS.
395 LLVM_ABI Error validate(bool Deep, HashingFuncT Hasher) const;
396
397 /// Checks that \p ID exists in the index. It is allowed to not have data
398 /// associated with it.
400
401 /// How to fault-in nodes if an upstream database is used.
402 enum class FaultInPolicy {
403 /// Copy only the requested node.
405 /// Copy the the entire graph of a node.
407 };
408
409 /// Open the on-disk store from a directory.
410 ///
411 /// \param Path directory for the on-disk store. The directory will be created
412 /// if it doesn't exist.
413 /// \param HashName Identifier name for the hashing algorithm that is going to
414 /// be used.
415 /// \param HashByteSize Size for the object digest hash bytes.
416 /// \param UpstreamDB Optional on-disk store to be used for faulting-in nodes
417 /// if they don't exist in the primary store. The upstream store is only used
418 /// for reading nodes, new nodes are only written to the primary store. User
419 /// need to make sure \p UpstreamDB outlives current instance of
420 /// OnDiskGraphDB and the common usage is to have an \p UnifiedOnDiskCache to
421 /// manage both.
422 /// \param Policy If \p UpstreamDB is provided, controls how nodes are copied
423 /// to primary store. This is recorded at creation time and subsequent opens
424 /// need to pass the same policy otherwise the \p open will fail.
426 open(StringRef Path, StringRef HashName, unsigned HashByteSize,
427 OnDiskGraphDB *UpstreamDB = nullptr,
428 std::shared_ptr<OnDiskCASLogger> Logger = nullptr,
429 FaultInPolicy Policy = FaultInPolicy::FullTree);
430
432
433private:
434 /// Forward declaration for a proxy for an ondisk index record.
435 struct IndexProxy;
436
437 enum class ObjectPresence {
438 Missing,
439 InPrimaryDB,
440 OnlyInUpstreamDB,
441 };
442
443 /// Check if object exists and if it is on upstream only.
444 LLVM_ABI Expected<ObjectPresence> getObjectPresence(ObjectID Ref,
445 bool CheckUpstream) const;
446
447 /// When \p load is called for a node that doesn't exist, this function tries
448 /// to load it from the upstream store and copy it to the primary one.
449 Expected<std::optional<ObjectHandle>> faultInFromUpstream(ObjectID PrimaryID);
450
451 /// Import the entire tree from upstream with \p UpstreamNode as root.
452 Error importFullTree(ObjectID PrimaryID, ObjectHandle UpstreamNode);
453 /// Import only the \param UpstreamNode.
454 Error importSingleNode(ObjectID PrimaryID, ObjectHandle UpstreamNode);
455 Error importUpstreamData(ObjectID PrimaryID, ArrayRef<ObjectID> PrimaryRefs,
456 ObjectHandle UpstreamNode);
457
458 enum class InternalUpstreamImportKind { Leaf, Leaf0 };
459 /// Private \c storeFile than optimizes internal upstream database imports.
460 Error storeFile(ObjectID ID, StringRef FilePath,
461 std::optional<InternalUpstreamImportKind> ImportKind);
462
463 /// Found the IndexProxy for the hash.
465
466 /// Get path for creating standalone data file.
467 void getStandalonePath(StringRef FileSuffix, FileOffset IndexOffset,
468 SmallVectorImpl<char> &Path) const;
469 /// Create a standalone leaf file.
470 Error createStandaloneLeaf(IndexProxy &I, ArrayRef<char> Data);
471
472 /// \name Helper functions for internal data structures.
473 /// \{
474 static InternalRef getInternalRef(ObjectID Ref) {
475 return InternalRef::getFromRawData(Ref.getOpaqueData());
476 }
477
478 static ObjectID getExternalReference(InternalRef Ref) {
479 return ObjectID::fromOpaqueData(Ref.getRawData());
480 }
481
482 static ObjectID getExternalReference(const IndexProxy &I);
483
484 static InternalRef makeInternalRef(FileOffset IndexOffset);
485
486 LLVM_ABI Expected<ArrayRef<uint8_t>> getDigest(InternalRef Ref) const;
487
488 ArrayRef<uint8_t> getDigest(const IndexProxy &I) const;
489
490 Expected<IndexProxy> getIndexProxyFromRef(InternalRef Ref) const;
491
493 getIndexProxyFromPointer(OnDiskTrieRawHashMap::ConstOnDiskPtr P) const;
494
495 LLVM_ABI InternalRefArrayRef getInternalRefs(ObjectHandle Node) const;
496 /// \}
497
498 /// Get the atomic variable that keeps track of the standalone data storage
499 /// size.
500 std::atomic<uint64_t> &standaloneStorageSize() const;
501
502 /// Increase the standalone data size.
503 void recordStandaloneSizeIncrease(size_t SizeIncrease);
504 /// Get the standalone data size.
505 uint64_t getStandaloneStorageSize() const;
506
507 // Private constructor.
508 OnDiskGraphDB(StringRef RootPath, OnDiskTrieRawHashMap Index,
509 OnDiskDataAllocator DataPool, OnDiskGraphDB *UpstreamDB,
510 FaultInPolicy Policy, std::shared_ptr<OnDiskCASLogger> Logger);
511
512 /// Mapping from hash to object reference.
513 ///
514 /// Data type is TrieRecord.
515 OnDiskTrieRawHashMap Index;
516
517 /// Storage for most objects.
518 ///
519 /// Data type is DataRecordHandle.
520 OnDiskDataAllocator DataPool;
521
522 /// A StandaloneDataMap.
523 void *StandaloneData = nullptr;
524
525 /// Path to the root directory.
526 std::string RootPath;
527
528 /// Optional on-disk store to be used for faulting-in nodes.
529 OnDiskGraphDB *UpstreamDB = nullptr;
530
531 /// The policy used to fault in data from upstream.
532 FaultInPolicy FIPolicy;
533
534 /// Debug Logger.
535 std::shared_ptr<OnDiskCASLogger> Logger;
536};
537
538} // namespace llvm::cas::ondisk
539
540#endif // LLVM_CAS_ONDISKGRAPHDB_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Mark last scratch load
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_ABI
Definition Compiler.h:215
#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 file declares interface for OnDiskDataAllocator, a file backed data pool can be used to allocate...
static void getStandalonePath(StringRef RootPath, StringRef Prefix, FileOffset IndexOffset, SmallVectorImpl< char > &Path)
This file declares interface for OnDiskTrieRawHashMap, a thread-safe and (mostly) lock-free hash map ...
#define P(N)
This file defines the PointerUnion class, which is a discriminated union of pointer types.
Value * RHS
Value * LHS
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
Tagged union holding either a T or a Error.
Definition Error.h:485
Logging utility - given an ordered specification of features, and assuming a scalar reward,...
This interface provides simple read-only access to a block of memory, and provides simple methods for...
A discriminated union of two or more pointer types, with the discriminator in the low bits of the poi...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
FileOffset is a wrapper around uint64_t to represent the offset of data from the beginning of the fil...
Definition FileOffset.h:24
Handle to a loaded object in a ObjectStore instance.
Compact 4 byte reference inside OnDiskGraphDB for smaller references.
static std::optional< InternalRef4B > tryToShrink(InternalRef Ref)
Shrink to 4B reference.
ptrdiff_t operator-(const iterator &RHS) const
bool operator==(const iterator &RHS) const
static iterator fromOpaqueData(uint64_t Opaque)
bool operator<(const iterator &RHS) const
Array of internal node references.
InternalRef operator[](ptrdiff_t N) const
Array accessor.
ArrayRef< uint8_t > getBuffer() const
InternalRefArrayRef(std::nullopt_t=std::nullopt)
InternalRefArrayRef(ArrayRef< InternalRef4B > Refs)
bool operator==(const InternalRefArrayRef &RHS) const
InternalRefArrayRef(ArrayRef< InternalRef > Refs)
Standard 8 byte reference inside OnDiskGraphDB.
friend bool operator==(InternalRef LHS, InternalRef RHS)
FileOffset getFileOffset() const
static InternalRef getFromRawData(uint64_t Data)
static InternalRef getFromOffset(FileOffset Offset)
Handle for a loaded node object.
static LLVM_ABI ObjectHandle fromFileOffset(FileOffset Offset)
static LLVM_ABI ObjectHandle fromMemory(uintptr_t Ptr)
friend bool operator!=(const ObjectHandle &LHS, const ObjectHandle &RHS)
friend bool operator==(const ObjectHandle &LHS, const ObjectHandle &RHS)
Reference to a node.
friend bool operator!=(const ObjectID &LHS, const ObjectID &RHS)
uint64_t getOpaqueData() const
friend bool operator==(const ObjectID &LHS, const ObjectID &RHS)
static ObjectID fromOpaqueData(uint64_t Opaque)
On-disk CAS nodes database, independent of a particular hashing algorithm.
FaultInPolicy
How to fault-in nodes if an upstream database is used.
@ FullTree
Copy the the entire graph of a node.
@ SingleNode
Copy only the requested node.
LLVM_ABI void print(raw_ostream &OS) const
LLVM_ABI Error validateObjectID(ObjectID ID) const
Checks that ID exists in the index.
LLVM_ABI std::unique_ptr< MemoryBuffer > getStandaloneMemoryBuffer(ObjectHandle Node, StringRef Name, bool RequiresNullTerminator) const
Get a MemoryBuffer for Node's data that stays valid after this database is destroyed.
LLVM_ABI Expected< bool > isMaterialized(ObjectID Ref)
Check whether the object associated with Ref is stored in the CAS.
LLVM_ABI Error validate(bool Deep, HashingFuncT Hasher) const
Validate the OnDiskGraphDB.
object_refs_range getObjectRefs(ObjectHandle Node) const
LLVM_ABI unsigned getHardStorageLimitUtilization() const
LLVM_ABI 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
LLVM_ABI FileBackedData getInternalFileBackedObjectData(ObjectHandle Node) const
Provides access to the underlying file path, that represents an object leaf node, when available.
LLVM_ABI Error storeFile(ObjectID ID, StringRef FilePath)
Associates the data of a file with a particular object ID.
LLVM_ABI size_t getStorageSize() const
static LLVM_ABI 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.
bool containsObject(ObjectID Ref, bool CheckUpstream=true) const
Check whether the object associated with Ref is stored in the CAS.
LLVM_ABI Expected< ObjectID > getReference(ArrayRef< uint8_t > Hash)
Form a reference for the provided hash.
function_ref< void( ArrayRef< ArrayRef< uint8_t > >, ArrayRef< char >, SmallVectorImpl< uint8_t > &)> HashingFuncT
Hashing function type for validation.
LLVM_ABI ArrayRef< char > getObjectData(ObjectHandle Node) const
LLVM_ABI std::optional< ObjectID > getExistingReference(ArrayRef< uint8_t > Digest, bool CheckUpstream=true)
Get an existing reference to the object Digest.
object_refs_iterator & operator-=(ptrdiff_t N)
bool operator<(const object_refs_iterator &RHS) const
object_refs_iterator & operator+=(ptrdiff_t N)
ptrdiff_t operator-(const object_refs_iterator &RHS) const
bool operator==(const object_refs_iterator &RHS) const
ObjectID operator[](ptrdiff_t N) const
static object_refs_iterator fromOpaqueData(uint64_t Opaque)
object_refs_iterator(InternalRefArrayRef::iterator I)
An efficient, type-erasing, non-owning reference to a callable.
CRTP base class which implements the entire standard iterator facade in terms of a minimal subset of ...
Definition iterator.h:80
A range adaptor for a pair of iterators.
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
llvm::iterator_range< object_refs_iterator > object_refs_range
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:578
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
@ Ref
The access may reference the value stored in memory.
Definition ModRef.h:32
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
Definition Error.h:769
ArrayRef(const T &OneElt) -> ArrayRef< T >
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
void consumeError(Error Err)
Consume a Error without doing anything.
Definition Error.h:1106
#define N
Proxy for an on-disk index record.
std::string FilePath
The file path of the object node.
bool IsFileNulTerminated
Whether the file of the object leaf node has an extra nul appended at the end.
Encapsulates file info for an underlying object node.
std::optional< FileInfoTy > FileInfo
File information for the object, if available.
ArrayRef< char > Data
The data of the object node.