LLVM 22.0.0git
UnifiedOnDiskCache.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/// \file
10/// Encapsulates \p OnDiskGraphDB and \p OnDiskKeyValueDB instances within one
11/// directory while also restricting storage growth with a scheme of chaining
12/// the two most recent directories (primary & upstream), where the primary
13/// "faults-in" data from the upstream one. When the primary (most recent)
14/// directory exceeds its intended limit a new empty directory becomes the
15/// primary one.
16///
17/// Within the top-level directory (the path that \p UnifiedOnDiskCache::open
18/// receives) there are directories named like this:
19///
20/// 'v<version>.<x>'
21/// 'v<version>.<x+1>'
22/// 'v<version>.<x+2>'
23/// ...
24///
25/// 'version' is the version integer for this \p UnifiedOnDiskCache's scheme and
26/// the part after the dot is an increasing integer. The primary directory is
27/// the one with the highest integer and the upstream one is the directory
28/// before it. For example, if the sub-directories contained are:
29///
30/// 'v1.5', 'v1.6', 'v1.7', 'v1.8'
31///
32/// Then the primary one is 'v1.8', the upstream one is 'v1.7', and the rest are
33/// unused directories that can be safely deleted at any time and by any
34/// process.
35///
36/// Contained within the top-level directory is a file named "lock" which is
37/// used for processes to take shared or exclusive locks for the contents of the
38/// top directory. While a \p UnifiedOnDiskCache is open it keeps a shared lock
39/// for the top-level directory; when it closes, if the primary sub-directory
40/// exceeded its limit, it attempts to get an exclusive lock in order to create
41/// a new empty primary directory; if it can't get the exclusive lock it gives
42/// up and lets the next \p UnifiedOnDiskCache instance that closes to attempt
43/// again.
44///
45/// The downside of this scheme is that while \p UnifiedOnDiskCache is open on a
46/// directory, by any process, the storage size in that directory will keep
47/// growing unrestricted. But the major benefit is that garbage-collection can
48/// be triggered on a directory concurrently, at any time and by any process,
49/// without affecting any active readers/writers in the same process or other
50/// processes.
51///
52/// The \c UnifiedOnDiskCache also provides validation and recovery on top of
53/// the underlying on-disk storage. The low-level storage is designed to remain
54/// coherent across regular process crashes, but may be invalid after power loss
55/// or similar system failures. \c UnifiedOnDiskCache::validateIfNeeded allows
56/// validating the contents once per boot and can recover by marking invalid
57/// data for garbage collection.
58///
59/// The data recovery described above requires exclusive access to the CAS, and
60/// it is an error to attempt recovery if the CAS is open in any process/thread.
61/// In order to maximize backwards compatibility with tools that do not perform
62/// validation before opening the CAS, we do not attempt to get exclusive access
63/// until recovery is actually performed, meaning as long as the data is valid
64/// it will not conflict with concurrent use.
65//
66//===----------------------------------------------------------------------===//
67
69#include "BuiltinCAS.h"
70#include "OnDiskCommon.h"
71#include "llvm/ADT/STLExtras.h"
72#include "llvm/ADT/ScopeExit.h"
76#include "llvm/ADT/StringRef.h"
81#include "llvm/Support/Errc.h"
82#include "llvm/Support/Error.h"
87#include "llvm/Support/Path.h"
90#include <optional>
91
92using namespace llvm;
93using namespace llvm::cas;
94using namespace llvm::cas::ondisk;
95
96/// FIXME: When the version of \p DBDirPrefix is bumped up we need to figure out
97/// how to handle the leftover sub-directories of the previous version, within
98/// the \p UnifiedOnDiskCache::collectGarbage function.
99static constexpr StringLiteral DBDirPrefix = "v1.";
100
101static constexpr StringLiteral ValidationFilename = "v1.validation";
102static constexpr StringLiteral CorruptPrefix = "corrupt.";
103
109
112 // little endian encoded.
114 static_assert(ValBytes.size() == sizeof(ID.getOpaqueData()));
115 support::endian::write64le(ValBytes.data(), ID.getOpaqueData());
116 return ValBytes;
117}
118
120UnifiedOnDiskCache::faultInFromUpstreamKV(ArrayRef<uint8_t> Key) {
121 assert(UpstreamGraphDB);
122 assert(UpstreamKVDB);
123
124 std::optional<ArrayRef<char>> UpstreamValue;
125 if (Error E = UpstreamKVDB->get(Key).moveInto(UpstreamValue))
126 return std::move(E);
127 if (!UpstreamValue)
128 return std::nullopt;
129
130 // The value is the \p ObjectID in the context of the upstream
131 // \p OnDiskGraphDB instance. Translate it to the context of the primary
132 // \p OnDiskGraphDB instance.
133 ObjectID UpstreamID = getObjectIDFromValue(*UpstreamValue);
134 auto PrimaryID =
135 PrimaryGraphDB->getReference(UpstreamGraphDB->getDigest(UpstreamID));
136 if (LLVM_UNLIKELY(!PrimaryID))
137 return PrimaryID.takeError();
138 return PrimaryKVDB->put(Key, getValueFromObjectID(*PrimaryID));
139}
140
141/// \returns all the 'v<version>.<x>' names of sub-directories, sorted with
142/// ascending order of the integer after the dot. Corrupt directories, if
143/// included, will come first.
145getAllDBDirs(StringRef Path, bool IncludeCorrupt = false) {
146 struct DBDir {
147 uint64_t Order;
148 std::string Name;
149 };
150 SmallVector<DBDir> FoundDBDirs;
151
152 std::error_code EC;
153 for (sys::fs::directory_iterator DirI(Path, EC), DirE; !EC && DirI != DirE;
154 DirI.increment(EC)) {
155 if (DirI->type() != sys::fs::file_type::directory_file)
156 continue;
157 StringRef SubDir = sys::path::filename(DirI->path());
158 if (IncludeCorrupt && SubDir.starts_with(CorruptPrefix)) {
159 FoundDBDirs.push_back({0, std::string(SubDir)});
160 continue;
161 }
162 if (!SubDir.starts_with(DBDirPrefix))
163 continue;
164 uint64_t Order;
165 if (SubDir.substr(DBDirPrefix.size()).getAsInteger(10, Order))
167 "unexpected directory " + DirI->path());
168 FoundDBDirs.push_back({Order, std::string(SubDir)});
169 }
170 if (EC)
171 return createFileError(Path, EC);
172
173 llvm::sort(FoundDBDirs, [](const DBDir &LHS, const DBDir &RHS) -> bool {
174 return LHS.Order < RHS.Order;
175 });
176
178 for (DBDir &Dir : FoundDBDirs)
179 DBDirs.push_back(std::move(Dir.Name));
180 return DBDirs;
181}
182
184 auto DBDirs = getAllDBDirs(Path, /*IncludeCorrupt=*/true);
185 if (!DBDirs)
186 return DBDirs.takeError();
187
188 // FIXME: When the version of \p DBDirPrefix is bumped up we need to figure
189 // out how to handle the leftover sub-directories of the previous version.
190
191 for (unsigned Keep = 2; Keep > 0 && !DBDirs->empty(); --Keep) {
192 StringRef Back(DBDirs->back());
193 if (Back.starts_with(CorruptPrefix))
194 break;
195 DBDirs->pop_back();
196 }
197 return *DBDirs;
198}
199
200/// \returns Given a sub-directory named 'v<version>.<x>', it outputs the
201/// 'v<version>.<x+1>' name.
205 bool Failed = DBDir.substr(DBDirPrefix.size()).getAsInteger(10, Count);
206 assert(!Failed);
207 (void)Failed;
208 OS << DBDirPrefix << Count + 1;
209}
210
211static Error validateOutOfProcess(StringRef LLVMCasBinary, StringRef RootPath,
212 bool CheckHash) {
213 SmallVector<StringRef> Args{LLVMCasBinary, "-cas", RootPath, "-validate"};
214 if (CheckHash)
215 Args.push_back("-check-hash");
216
217 llvm::SmallString<128> StdErrPath;
218 int StdErrFD = -1;
219 if (std::error_code EC = sys::fs::createTemporaryFile(
220 "llvm-cas-validate-stderr", "txt", StdErrFD, StdErrPath,
222 return createStringError(EC, "failed to create temporary file");
223 FileRemover OutputRemover(StdErrPath.c_str());
224
225 std::optional<llvm::StringRef> Redirects[] = {
226 {""}, // stdin = /dev/null
227 {""}, // stdout = /dev/null
228 StdErrPath.str(),
229 };
230
231 std::string ErrMsg;
232 int Result =
233 sys::ExecuteAndWait(LLVMCasBinary, Args, /*Env=*/std::nullopt, Redirects,
234 /*SecondsToWait=*/120, /*MemoryLimit=*/0, &ErrMsg);
235
236 if (Result == -1)
237 return createStringError("failed to exec " + join(Args, " ") + ": " +
238 ErrMsg);
239 if (Result != 0) {
240 llvm::SmallString<64> Err("cas contents invalid");
241 if (!ErrMsg.empty()) {
242 Err += ": ";
243 Err += ErrMsg;
244 }
245 auto StdErrBuf = MemoryBuffer::getFile(StdErrPath.c_str());
246 if (StdErrBuf && !(*StdErrBuf)->getBuffer().empty()) {
247 Err += ": ";
248 Err += (*StdErrBuf)->getBuffer();
249 }
250 return createStringError(Err);
251 }
252 return Error::success();
253}
254
255static Error validateInProcess(StringRef RootPath, StringRef HashName,
256 unsigned HashByteSize, bool CheckHash) {
257 std::shared_ptr<UnifiedOnDiskCache> UniDB;
258 if (Error E = UnifiedOnDiskCache::open(RootPath, std::nullopt, HashName,
259 HashByteSize)
260 .moveInto(UniDB))
261 return E;
263 if (Error E = CAS->validate(CheckHash))
264 return E;
266 if (Error E = Cache->validate())
267 return E;
268 return Error::success();
269}
270
272 StringRef RootPath, StringRef HashName, unsigned HashByteSize,
273 bool CheckHash, bool AllowRecovery, bool ForceValidation,
274 std::optional<StringRef> LLVMCasBinaryPath) {
275 if (std::error_code EC = sys::fs::create_directories(RootPath))
276 return createFileError(RootPath, EC);
277
278 SmallString<256> PathBuf(RootPath);
280 int FD = -1;
281 if (std::error_code EC = sys::fs::openFileForReadWrite(
283 return createFileError(PathBuf, EC);
284 assert(FD != -1);
285
287 auto CloseFile = make_scope_exit([&]() { sys::fs::closeFile(File); });
288
289 if (std::error_code EC = lockFileThreadSafe(FD, sys::fs::LockKind::Exclusive))
290 return createFileError(PathBuf, EC);
291 auto UnlockFD = make_scope_exit([&]() { unlockFileThreadSafe(FD); });
292
293 SmallString<8> Bytes;
294 if (Error E = sys::fs::readNativeFileToEOF(File, Bytes))
295 return createFileError(PathBuf, std::move(E));
296
297 uint64_t ValidationBootTime = 0;
298 if (!Bytes.empty() &&
299 StringRef(Bytes).trim().getAsInteger(10, ValidationBootTime))
301 "expected integer");
302
303 static uint64_t BootTime = 0;
304 if (BootTime == 0)
305 if (Error E = getBootTime().moveInto(BootTime))
306 return std::move(E);
307
308 if (ValidationBootTime == BootTime && !ForceValidation)
310
311 // Validate!
312 bool NeedsRecovery = false;
313 if (Error E =
314 LLVMCasBinaryPath
315 ? validateOutOfProcess(*LLVMCasBinaryPath, RootPath, CheckHash)
316 : validateInProcess(RootPath, HashName, HashByteSize,
317 CheckHash)) {
318 if (AllowRecovery) {
319 consumeError(std::move(E));
320 NeedsRecovery = true;
321 } else {
322 return std::move(E);
323 }
324 }
325
326 if (NeedsRecovery) {
328 sys::path::append(PathBuf, "lock");
329
330 int LockFD = -1;
331 if (std::error_code EC = sys::fs::openFileForReadWrite(
332 PathBuf, LockFD, sys::fs::CD_OpenAlways, sys::fs::OF_None))
333 return createFileError(PathBuf, EC);
335 auto CloseLock = make_scope_exit([&]() { sys::fs::closeFile(LockFile); });
336 if (std::error_code EC = tryLockFileThreadSafe(LockFD)) {
337 if (EC == std::errc::no_lock_available)
338 return createFileError(
339 PathBuf, EC,
340 "CAS validation requires exclusive access but CAS was in use");
341 return createFileError(PathBuf, EC);
342 }
343 auto UnlockFD = make_scope_exit([&]() { unlockFileThreadSafe(LockFD); });
344
345 auto DBDirs = getAllDBDirs(RootPath);
346 if (!DBDirs)
347 return DBDirs.takeError();
348
349 for (StringRef DBDir : *DBDirs) {
351 sys::path::append(PathBuf, DBDir);
352 std::error_code EC;
353 int Attempt = 0, MaxAttempts = 100;
354 SmallString<128> GCPath;
355 for (; Attempt < MaxAttempts; ++Attempt) {
356 GCPath.assign(RootPath);
357 sys::path::append(GCPath, CorruptPrefix + std::to_string(Attempt) +
358 "." + DBDir);
359 EC = sys::fs::rename(PathBuf, GCPath);
360 // Darwin uses ENOTEMPTY. Linux may return either ENOTEMPTY or EEXIST.
362 break;
363 }
364 if (Attempt == MaxAttempts)
365 return createStringError(
366 EC, "rename " + PathBuf +
367 " failed: too many CAS directories awaiting pruning");
368 if (EC)
369 return createStringError(EC, "rename " + PathBuf + " to " + GCPath +
370 " failed: " + EC.message());
371 }
372 }
373
374 if (ValidationBootTime != BootTime) {
375 // Fix filename in case we have error to report.
378 if (std::error_code EC = sys::fs::resize_file(FD, 0))
379 return createFileError(PathBuf, EC);
380 raw_fd_ostream OS(FD, /*shouldClose=*/false);
381 OS.seek(0); // resize does not reset position
382 OS << BootTime << '\n';
383 if (OS.has_error())
384 return createFileError(PathBuf, OS.error());
385 }
386
388}
389
391UnifiedOnDiskCache::open(StringRef RootPath, std::optional<uint64_t> SizeLimit,
392 StringRef HashName, unsigned HashByteSize,
393 OnDiskGraphDB::FaultInPolicy FaultInPolicy) {
394 auto BypassSandbox = sys::sandbox::scopedDisable();
395
396 if (std::error_code EC = sys::fs::create_directories(RootPath))
397 return createFileError(RootPath, EC);
398
399 SmallString<256> PathBuf(RootPath);
400 sys::path::append(PathBuf, "lock");
401 int LockFD = -1;
402 if (std::error_code EC = sys::fs::openFileForReadWrite(
403 PathBuf, LockFD, sys::fs::CD_OpenAlways, sys::fs::OF_None))
404 return createFileError(PathBuf, EC);
405 assert(LockFD != -1);
406 // Locking the directory using shared lock, which will prevent other processes
407 // from creating a new chain (essentially while a \p UnifiedOnDiskCache
408 // instance holds a shared lock the storage for the primary directory will
409 // grow unrestricted).
410 if (std::error_code EC =
412 return createFileError(PathBuf, EC);
413
414 auto DBDirs = getAllDBDirs(RootPath);
415 if (!DBDirs)
416 return DBDirs.takeError();
417 if (DBDirs->empty())
418 DBDirs->push_back((Twine(DBDirPrefix) + "1").str());
419
420 assert(!DBDirs->empty());
421
422 /// If there is only one directory open databases on it. If there are 2 or
423 /// more directories, get the most recent directories and chain them, with the
424 /// most recent being the primary one. The remaining directories are unused
425 /// data than can be garbage-collected.
426 auto UniDB = std::unique_ptr<UnifiedOnDiskCache>(new UnifiedOnDiskCache());
427 std::unique_ptr<OnDiskGraphDB> UpstreamGraphDB;
428 std::unique_ptr<OnDiskKeyValueDB> UpstreamKVDB;
429 if (DBDirs->size() > 1) {
430 StringRef UpstreamDir = *(DBDirs->end() - 2);
431 PathBuf = RootPath;
432 sys::path::append(PathBuf, UpstreamDir);
433 if (Error E = OnDiskGraphDB::open(PathBuf, HashName, HashByteSize,
434 /*UpstreamDB=*/nullptr, FaultInPolicy)
435 .moveInto(UpstreamGraphDB))
436 return std::move(E);
437 if (Error E = OnDiskKeyValueDB::open(PathBuf, HashName, HashByteSize,
438 /*ValueName=*/"objectid",
439 /*ValueSize=*/sizeof(uint64_t))
440 .moveInto(UpstreamKVDB))
441 return std::move(E);
442 }
443
444 StringRef PrimaryDir = *(DBDirs->end() - 1);
445 PathBuf = RootPath;
446 sys::path::append(PathBuf, PrimaryDir);
447 std::unique_ptr<OnDiskGraphDB> PrimaryGraphDB;
448 if (Error E = OnDiskGraphDB::open(PathBuf, HashName, HashByteSize,
449 UpstreamGraphDB.get(), FaultInPolicy)
450 .moveInto(PrimaryGraphDB))
451 return std::move(E);
452 std::unique_ptr<OnDiskKeyValueDB> PrimaryKVDB;
453 // \p UnifiedOnDiskCache does manual chaining for key-value requests,
454 // including an extra translation step of the value during fault-in.
455 if (Error E =
456 OnDiskKeyValueDB::open(PathBuf, HashName, HashByteSize,
457 /*ValueName=*/"objectid",
458 /*ValueSize=*/sizeof(uint64_t), UniDB.get())
459 .moveInto(PrimaryKVDB))
460 return std::move(E);
461
462 UniDB->RootPath = RootPath;
463 UniDB->SizeLimit = SizeLimit.value_or(0);
464 UniDB->LockFD = LockFD;
465 UniDB->NeedsGarbageCollection = DBDirs->size() > 2;
466 UniDB->PrimaryDBDir = PrimaryDir;
467 UniDB->UpstreamGraphDB = std::move(UpstreamGraphDB);
468 UniDB->PrimaryGraphDB = std::move(PrimaryGraphDB);
469 UniDB->UpstreamKVDB = std::move(UpstreamKVDB);
470 UniDB->PrimaryKVDB = std::move(PrimaryKVDB);
471
472 return std::move(UniDB);
473}
474
475void UnifiedOnDiskCache::setSizeLimit(std::optional<uint64_t> SizeLimit) {
476 this->SizeLimit = SizeLimit.value_or(0);
477}
478
480 uint64_t TotalSize = getPrimaryStorageSize();
481 if (UpstreamGraphDB)
482 TotalSize += UpstreamGraphDB->getStorageSize();
483 if (UpstreamKVDB)
484 TotalSize += UpstreamKVDB->getStorageSize();
485 return TotalSize;
486}
487
488uint64_t UnifiedOnDiskCache::getPrimaryStorageSize() const {
489 return PrimaryGraphDB->getStorageSize() + PrimaryKVDB->getStorageSize();
490}
491
493 uint64_t CurSizeLimit = SizeLimit;
494 if (!CurSizeLimit)
495 return false;
496
497 // If the hard limit is beyond 85%, declare above limit and request clean up.
498 unsigned CurrentPercent =
499 std::max(PrimaryGraphDB->getHardStorageLimitUtilization(),
500 PrimaryKVDB->getHardStorageLimitUtilization());
501 if (CurrentPercent > 85)
502 return true;
503
504 // We allow each of the directories in the chain to reach up to half the
505 // intended size limit. Check whether the primary directory has exceeded half
506 // the limit or not, in order to decide whether we need to start a new chain.
507 //
508 // We could check the size limit against the sum of sizes of both the primary
509 // and upstream directories but then if the upstream is significantly larger
510 // than the intended limit, it would trigger a new chain to be created before
511 // the primary has reached its own limit. Essentially in such situation we
512 // prefer reclaiming the storage later in order to have more consistent cache
513 // hits behavior.
514 return (CurSizeLimit / 2) < getPrimaryStorageSize();
515}
516
517Error UnifiedOnDiskCache::close(bool CheckSizeLimit) {
518 auto BypassSandbox = sys::sandbox::scopedDisable();
519
520 if (LockFD == -1)
521 return Error::success(); // already closed.
522 auto CloseLock = make_scope_exit([&]() {
523 assert(LockFD >= 0);
525 sys::fs::closeFile(LockFile);
526 LockFD = -1;
527 });
528
529 bool ExceededSizeLimit = CheckSizeLimit ? hasExceededSizeLimit() : false;
530 UpstreamKVDB.reset();
531 PrimaryKVDB.reset();
532 UpstreamGraphDB.reset();
533 PrimaryGraphDB.reset();
534 if (std::error_code EC = unlockFileThreadSafe(LockFD))
535 return createFileError(RootPath, EC);
536
537 if (!ExceededSizeLimit)
538 return Error::success();
539
540 // The primary directory exceeded its intended size limit. Try to get an
541 // exclusive lock in order to create a new primary directory for next time
542 // this \p UnifiedOnDiskCache path is opened.
543
544 if (std::error_code EC = tryLockFileThreadSafe(
545 LockFD, std::chrono::milliseconds(0), sys::fs::LockKind::Exclusive)) {
546 if (EC == errc::no_lock_available)
547 return Error::success(); // couldn't get exclusive lock, give up.
548 return createFileError(RootPath, EC);
549 }
550 auto UnlockFile = make_scope_exit([&]() { unlockFileThreadSafe(LockFD); });
551
552 // Managed to get an exclusive lock which means there are no other open
553 // \p UnifiedOnDiskCache instances for the same path, so we can safely start a
554 // new primary directory. To start a new primary directory we just have to
555 // create a new empty directory with the next consecutive index; since this is
556 // an atomic operation we will leave the top-level directory in a consistent
557 // state even if the process dies during this code-path.
558
559 SmallString<256> PathBuf(RootPath);
560 raw_svector_ostream OS(PathBuf);
562 getNextDBDirName(PrimaryDBDir, OS);
563 if (std::error_code EC = sys::fs::create_directory(PathBuf))
564 return createFileError(PathBuf, EC);
565
566 NeedsGarbageCollection = true;
567 return Error::success();
568}
569
570UnifiedOnDiskCache::UnifiedOnDiskCache() = default;
571
573
575 auto DBDirs = getAllGarbageDirs(Path);
576 if (!DBDirs)
577 return DBDirs.takeError();
578
579 SmallString<256> PathBuf(Path);
580 for (StringRef UnusedSubDir : *DBDirs) {
581 sys::path::append(PathBuf, UnusedSubDir);
582 if (std::error_code EC = sys::fs::remove_directories(PathBuf))
583 return createFileError(PathBuf, EC);
585 }
586 return Error::success();
587}
588
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file contains the declaration of the ActionCache class, which is the base class for ActionCache ...
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_UNLIKELY(EXPR)
Definition Compiler.h:336
This declares OnDiskGraphDB, an ondisk CAS database with a fixed length hash.
This declares OnDiskKeyValueDB, a key value storage database of fixed size key and value.
This file contains some templates that are useful if you are working with the STL at all.
This file defines the make_scope_exit function, which executes user-defined cleanup logic at scope ex...
This file defines the SmallString class.
This file defines the SmallVector class.
This file contains some functions that are useful when dealing with strings.
static constexpr StringLiteral DBDirPrefix
FIXME: When the version of DBDirPrefix is bumped up we need to figure out how to handle the leftover ...
static Error validateInProcess(StringRef RootPath, StringRef HashName, unsigned HashByteSize, bool CheckHash)
static Expected< SmallVector< std::string, 4 > > getAllGarbageDirs(StringRef Path)
static constexpr StringLiteral ValidationFilename
static constexpr StringLiteral CorruptPrefix
static void getNextDBDirName(StringRef DBDir, llvm::raw_ostream &OS)
static Error validateOutOfProcess(StringRef LLVMCasBinary, StringRef RootPath, bool CheckHash)
static Expected< SmallVector< std::string, 4 > > getAllDBDirs(StringRef Path, bool IncludeCorrupt=false)
Value * RHS
Value * LHS
ArrayRef - 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
static ErrorSuccess success()
Create a success value.
Definition Error.h:336
Tagged union holding either a T or a Error.
Definition Error.h:485
FileRemover - This class is a simple object meant to be stack allocated.
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition SmallString.h:26
void assign(StringRef RHS)
Assign from a StringRef.
Definition SmallString.h:51
const char * c_str()
StringRef str() const
Explicit conversion to StringRef.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
A wrapper around a string literal that serves as a proxy for constructing global tables of StringRefs...
Definition StringRef.h:864
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
bool getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
Definition StringRef.h:472
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition StringRef.h:573
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition StringRef.h:261
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
LLVM Value Representation.
Definition Value.h:75
Reference to a node.
static ObjectID fromOpaqueData(uint64_t Opaque)
FaultInPolicy
How to fault-in nodes if an upstream database is used.
static LLVM_ABI_FOR_TEST 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.
static LLVM_ABI_FOR_TEST Expected< std::unique_ptr< OnDiskKeyValueDB > > open(StringRef Path, StringRef HashName, unsigned KeySize, StringRef ValueName, size_t ValueSize, UnifiedOnDiskCache *UnifiedCache=nullptr)
Open the on-disk store from a directory.
LLVM_ABI_FOR_TEST uint64_t getStorageSize() const
static LLVM_ABI_FOR_TEST ValueBytes getValueFromObjectID(ObjectID ID)
static LLVM_ABI_FOR_TEST Expected< std::unique_ptr< UnifiedOnDiskCache > > open(StringRef Path, std::optional< uint64_t > SizeLimit, StringRef HashName, unsigned HashByteSize, OnDiskGraphDB::FaultInPolicy FaultInPolicy=OnDiskGraphDB::FaultInPolicy::FullTree)
Open a UnifiedOnDiskCache instance for a directory.
LLVM_ABI_FOR_TEST Error close(bool CheckSizeLimit=true)
This is called implicitly at destruction time, so it is not required for a client to call this.
static LLVM_ABI_FOR_TEST ObjectID getObjectIDFromValue(ArrayRef< char > Value)
Helper function to convert the value stored in KeyValueDB and ObjectID.
static Expected< ValidationResult > validateIfNeeded(StringRef Path, StringRef HashName, unsigned HashByteSize, bool CheckHash, bool AllowRecovery, bool ForceValidation, std::optional< StringRef > LLVMCasBinary)
Validate the data in Path, if needed to ensure correctness.
LLVM_ABI_FOR_TEST bool hasExceededSizeLimit() const
std::array< char, sizeof(uint64_t)> ValueBytes
Error collectGarbage()
Remove unused data from the current UnifiedOnDiskCache.
LLVM_ABI_FOR_TEST void setSizeLimit(std::optional< uint64_t > SizeLimit)
Set the size for limiting growth.
A raw_ostream that writes to a file descriptor.
bool has_error() const
Return the value of the flag in this raw_fd_ostream indicating whether an output error has been encou...
std::error_code error() const
uint64_t seek(uint64_t off)
Flushes the stream and repositions the underlying file descriptor position to the offset specified fr...
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
A raw_ostream that writes to an SmallVector or SmallString.
directory_iterator - Iterates through the entries in path.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
std::unique_ptr< ObjectStore > createObjectStoreFromUnifiedOnDiskCache(std::shared_ptr< ondisk::UnifiedOnDiskCache > UniDB)
std::unique_ptr< ActionCache > createActionCacheFromUnifiedOnDiskCache(std::shared_ptr< ondisk::UnifiedOnDiskCache > UniDB)
std::error_code lockFileThreadSafe(int FD, llvm::sys::fs::LockKind Kind)
Thread-safe alternative to sys::fs::lockFile.
std::error_code unlockFileThreadSafe(int FD)
Thread-safe alternative to sys::fs::unlockFile.
std::error_code tryLockFileThreadSafe(int FD, std::chrono::milliseconds Timeout=std::chrono::milliseconds(0), llvm::sys::fs::LockKind Kind=llvm::sys::fs::LockKind::Exclusive)
Thread-safe alternative to sys::fs::tryLockFile.
Expected< uint64_t > getBootTime()
Get boot time for the OS.
@ Valid
The data is already valid.
@ Recovered
The data was invalid, but was recovered.
@ Skipped
Validation was skipped, as it was not needed.
uint64_t read64le(const void *P)
Definition Endian.h:435
void write64le(void *P, uint64_t V)
Definition Endian.h:478
LLVM_ABI std::error_code closeFile(file_t &F)
Close the file object.
std::error_code openFileForReadWrite(const Twine &Name, int &ResultFD, CreationDisposition Disp, OpenFlags Flags, unsigned Mode=0666)
Opens the file with the given name in a write-only or read-write mode, returning its open file descri...
LLVM_ABI std::error_code rename(const Twine &from, const Twine &to)
Rename from to to.
LLVM_ABI Error readNativeFileToEOF(file_t FileHandle, SmallVectorImpl< char > &Buffer, ssize_t ChunkSize=DefaultReadChunkSize)
Reads from FileHandle until EOF, appending to Buffer in chunks of size ChunkSize.
Definition Path.cpp:1193
@ OF_Text
The file should be opened in text mode on platforms like z/OS that make this distinction.
Definition FileSystem.h:755
@ CD_OpenAlways
CD_OpenAlways - When opening a file:
Definition FileSystem.h:742
LLVM_ABI std::error_code create_directories(const Twine &path, bool IgnoreExisting=true, perms Perms=owner_all|group_all)
Create all the non-existent directories in path.
Definition Path.cpp:972
LLVM_ABI std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, int &ResultFD, SmallVectorImpl< char > &ResultPath, OpenFlags Flags=OF_None)
Create a file in the system temporary directory.
Definition Path.cpp:915
LLVM_ABI std::error_code resize_file(int FD, uint64_t Size)
Resize path to size.
LLVM_ABI file_t convertFDToNativeFile(int FD)
Converts from a Posix file descriptor number to a native file handle.
Definition FileSystem.h:991
LLVM_ABI std::error_code create_directory(const Twine &path, bool IgnoreExisting=true, perms Perms=owner_all|group_all)
Create the directory in path.
LLVM_ABI std::error_code remove_directories(const Twine &path, bool IgnoreErrors=true)
Recursively delete a directory.
LLVM_ABI StringRef get_separator(Style style=Style::native)
Return the preferred separator for this platform.
Definition Path.cpp:610
LLVM_ABI void remove_filename(SmallVectorImpl< char > &path, Style style=Style::native)
Remove the last component from path unless it is the root dir.
Definition Path.cpp:475
LLVM_ABI StringRef filename(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get filename.
Definition Path.cpp:578
LLVM_ABI void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
Definition Path.cpp:457
ScopedSetting scopedDisable()
Definition IOSandbox.h:36
LLVM_ABI int ExecuteAndWait(StringRef Program, ArrayRef< StringRef > Args, std::optional< ArrayRef< StringRef > > Env=std::nullopt, ArrayRef< std::optional< StringRef > > Redirects={}, unsigned SecondsToWait=0, unsigned MemoryLimit=0, std::string *ErrMsg=nullptr, bool *ExecutionFailed=nullptr, std::optional< ProcessStatistics > *ProcStat=nullptr, BitVector *AffinityMask=nullptr)
This function executes the program using the arguments provided.
Definition Program.cpp:32
This is an optimization pass for GlobalISel generic memory operations.
Error createFileError(const Twine &F, Error E)
Concatenate a source file path and/or name with an Error.
Definition Error.h:1399
detail::scope_exit< std::decay_t< Callable > > make_scope_exit(Callable &&F)
Definition ScopeExit.h:59
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
testing::Matcher< const detail::ErrorHolder & > Failed()
Definition Error.h:198
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition Error.h:1305
@ file_exists
Definition Errc.h:48
@ illegal_byte_sequence
Definition Errc.h:52
@ no_lock_available
Definition Errc.h:61
@ directory_not_empty
Definition Errc.h:46
void sort(IteratorTy Start, IteratorTy End)
Definition STLExtras.h:1634
FunctionAddr VTableAddr Count
Definition InstrProf.h:139
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
std::string join(IteratorT Begin, IteratorT End, StringRef Separator)
Joins the strings in the range [Begin, End), adding Separator between the elements.
void consumeError(Error Err)
Consume a Error without doing anything.
Definition Error.h:1083
@ Keep
No function return thunk.
Definition CodeGen.h:162