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"
86#include "llvm/Support/Path.h"
89#include <optional>
90
91#if __has_include(<sys/sysctl.h>)
92#include <sys/sysctl.h>
93#endif
94
95using namespace llvm;
96using namespace llvm::cas;
97using namespace llvm::cas::ondisk;
98
99/// FIXME: When the version of \p DBDirPrefix is bumped up we need to figure out
100/// how to handle the leftover sub-directories of the previous version, within
101/// the \p UnifiedOnDiskCache::collectGarbage function.
102static constexpr StringLiteral DBDirPrefix = "v1.";
103
104static constexpr StringLiteral ValidationFilename = "v1.validation";
105static constexpr StringLiteral CorruptPrefix = "corrupt.";
106
112
115 // little endian encoded.
117 static_assert(ValBytes.size() == sizeof(ID.getOpaqueData()));
118 support::endian::write64le(ValBytes.data(), ID.getOpaqueData());
119 return ValBytes;
120}
121
123UnifiedOnDiskCache::faultInFromUpstreamKV(ArrayRef<uint8_t> Key) {
124 assert(UpstreamGraphDB);
125 assert(UpstreamKVDB);
126
127 std::optional<ArrayRef<char>> UpstreamValue;
128 if (Error E = UpstreamKVDB->get(Key).moveInto(UpstreamValue))
129 return std::move(E);
130 if (!UpstreamValue)
131 return std::nullopt;
132
133 // The value is the \p ObjectID in the context of the upstream
134 // \p OnDiskGraphDB instance. Translate it to the context of the primary
135 // \p OnDiskGraphDB instance.
136 ObjectID UpstreamID = getObjectIDFromValue(*UpstreamValue);
137 auto PrimaryID =
138 PrimaryGraphDB->getReference(UpstreamGraphDB->getDigest(UpstreamID));
139 if (LLVM_UNLIKELY(!PrimaryID))
140 return PrimaryID.takeError();
141 return PrimaryKVDB->put(Key, getValueFromObjectID(*PrimaryID));
142}
143
144/// \returns all the 'v<version>.<x>' names of sub-directories, sorted with
145/// ascending order of the integer after the dot. Corrupt directories, if
146/// included, will come first.
148getAllDBDirs(StringRef Path, bool IncludeCorrupt = false) {
149 struct DBDir {
150 uint64_t Order;
151 std::string Name;
152 };
153 SmallVector<DBDir> FoundDBDirs;
154
155 std::error_code EC;
156 for (sys::fs::directory_iterator DirI(Path, EC), DirE; !EC && DirI != DirE;
157 DirI.increment(EC)) {
158 if (DirI->type() != sys::fs::file_type::directory_file)
159 continue;
160 StringRef SubDir = sys::path::filename(DirI->path());
161 if (IncludeCorrupt && SubDir.starts_with(CorruptPrefix)) {
162 FoundDBDirs.push_back({0, std::string(SubDir)});
163 continue;
164 }
165 if (!SubDir.starts_with(DBDirPrefix))
166 continue;
167 uint64_t Order;
168 if (SubDir.substr(DBDirPrefix.size()).getAsInteger(10, Order))
170 "unexpected directory " + DirI->path());
171 FoundDBDirs.push_back({Order, std::string(SubDir)});
172 }
173 if (EC)
174 return createFileError(Path, EC);
175
176 llvm::sort(FoundDBDirs, [](const DBDir &LHS, const DBDir &RHS) -> bool {
177 return LHS.Order < RHS.Order;
178 });
179
181 for (DBDir &Dir : FoundDBDirs)
182 DBDirs.push_back(std::move(Dir.Name));
183 return DBDirs;
184}
185
187 auto DBDirs = getAllDBDirs(Path, /*IncludeCorrupt=*/true);
188 if (!DBDirs)
189 return DBDirs.takeError();
190
191 // FIXME: When the version of \p DBDirPrefix is bumped up we need to figure
192 // out how to handle the leftover sub-directories of the previous version.
193
194 for (unsigned Keep = 2; Keep > 0 && !DBDirs->empty(); --Keep) {
195 StringRef Back(DBDirs->back());
196 if (Back.starts_with(CorruptPrefix))
197 break;
198 DBDirs->pop_back();
199 }
200 return *DBDirs;
201}
202
203/// \returns Given a sub-directory named 'v<version>.<x>', it outputs the
204/// 'v<version>.<x+1>' name.
208 bool Failed = DBDir.substr(DBDirPrefix.size()).getAsInteger(10, Count);
209 assert(!Failed);
210 (void)Failed;
211 OS << DBDirPrefix << Count + 1;
212}
213
214static Error validateOutOfProcess(StringRef LLVMCasBinary, StringRef RootPath,
215 bool CheckHash) {
216 SmallVector<StringRef> Args{LLVMCasBinary, "-cas", RootPath, "-validate"};
217 if (CheckHash)
218 Args.push_back("-check-hash");
219
220 llvm::SmallString<128> StdErrPath;
221 int StdErrFD = -1;
222 if (std::error_code EC = sys::fs::createTemporaryFile(
223 "llvm-cas-validate-stderr", "txt", StdErrFD, StdErrPath,
225 return createStringError(EC, "failed to create temporary file");
226 FileRemover OutputRemover(StdErrPath.c_str());
227
228 std::optional<llvm::StringRef> Redirects[] = {
229 {""}, // stdin = /dev/null
230 {""}, // stdout = /dev/null
231 StdErrPath.str(),
232 };
233
234 std::string ErrMsg;
235 int Result =
236 sys::ExecuteAndWait(LLVMCasBinary, Args, /*Env=*/std::nullopt, Redirects,
237 /*SecondsToWait=*/120, /*MemoryLimit=*/0, &ErrMsg);
238
239 if (Result == -1)
240 return createStringError("failed to exec " + join(Args, " ") + ": " +
241 ErrMsg);
242 if (Result != 0) {
243 llvm::SmallString<64> Err("cas contents invalid");
244 if (!ErrMsg.empty()) {
245 Err += ": ";
246 Err += ErrMsg;
247 }
248 auto StdErrBuf = MemoryBuffer::getFile(StdErrPath.c_str());
249 if (StdErrBuf && !(*StdErrBuf)->getBuffer().empty()) {
250 Err += ": ";
251 Err += (*StdErrBuf)->getBuffer();
252 }
253 return createStringError(Err);
254 }
255 return Error::success();
256}
257
258static Error validateInProcess(StringRef RootPath, StringRef HashName,
259 unsigned HashByteSize, bool CheckHash) {
260 std::shared_ptr<UnifiedOnDiskCache> UniDB;
261 if (Error E = UnifiedOnDiskCache::open(RootPath, std::nullopt, HashName,
262 HashByteSize)
263 .moveInto(UniDB))
264 return E;
266 if (Error E = CAS->validate(CheckHash))
267 return E;
269 if (Error E = Cache->validate())
270 return E;
271 return Error::success();
272}
273
275#if __has_include(<sys/sysctl.h>) && defined(KERN_BOOTTIME)
276 struct timeval TV;
277 size_t TVLen = sizeof(TV);
278 int KernBoot[2] = {CTL_KERN, KERN_BOOTTIME};
279 if (sysctl(KernBoot, 2, &TV, &TVLen, nullptr, 0) < 0)
281 "failed to get boottime");
282 if (TVLen != sizeof(TV))
283 return createStringError("sysctl kern.boottime unexpected format");
284 return TV.tv_sec;
285#elif defined(__linux__)
286 // Use the mtime for /proc, which is recreated during system boot.
287 // We could also read /proc/stat and search for 'btime'.
289 if (std::error_code EC = sys::fs::status("/proc", Status))
290 return createFileError("/proc", EC);
291 return Status.getLastModificationTime().time_since_epoch().count();
292#else
293 llvm::report_fatal_error("getBootTime unimplemented");
294#endif
295}
296
298 StringRef RootPath, StringRef HashName, unsigned HashByteSize,
299 bool CheckHash, bool AllowRecovery, bool ForceValidation,
300 std::optional<StringRef> LLVMCasBinaryPath) {
301 if (std::error_code EC = sys::fs::create_directories(RootPath))
302 return createFileError(RootPath, EC);
303
304 SmallString<256> PathBuf(RootPath);
306 int FD = -1;
307 if (std::error_code EC = sys::fs::openFileForReadWrite(
309 return createFileError(PathBuf, EC);
310 assert(FD != -1);
311
313 auto CloseFile = make_scope_exit([&]() { sys::fs::closeFile(File); });
314
315 if (std::error_code EC = lockFileThreadSafe(FD, sys::fs::LockKind::Exclusive))
316 return createFileError(PathBuf, EC);
317 auto UnlockFD = make_scope_exit([&]() { unlockFileThreadSafe(FD); });
318
319 SmallString<8> Bytes;
320 if (Error E = sys::fs::readNativeFileToEOF(File, Bytes))
321 return createFileError(PathBuf, std::move(E));
322
323 uint64_t ValidationBootTime = 0;
324 if (!Bytes.empty() &&
325 StringRef(Bytes).trim().getAsInteger(10, ValidationBootTime))
327 "expected integer");
328
329 static uint64_t BootTime = 0;
330 if (BootTime == 0)
331 if (Error E = getBootTime().moveInto(BootTime))
332 return std::move(E);
333
334 if (ValidationBootTime == BootTime && !ForceValidation)
336
337 // Validate!
338 bool NeedsRecovery = false;
339 if (Error E =
340 LLVMCasBinaryPath
341 ? validateOutOfProcess(*LLVMCasBinaryPath, RootPath, CheckHash)
342 : validateInProcess(RootPath, HashName, HashByteSize,
343 CheckHash)) {
344 if (AllowRecovery) {
345 consumeError(std::move(E));
346 NeedsRecovery = true;
347 } else {
348 return std::move(E);
349 }
350 }
351
352 if (NeedsRecovery) {
354 sys::path::append(PathBuf, "lock");
355
356 int LockFD = -1;
357 if (std::error_code EC = sys::fs::openFileForReadWrite(
358 PathBuf, LockFD, sys::fs::CD_OpenAlways, sys::fs::OF_None))
359 return createFileError(PathBuf, EC);
361 auto CloseLock = make_scope_exit([&]() { sys::fs::closeFile(LockFile); });
362 if (std::error_code EC = tryLockFileThreadSafe(LockFD)) {
363 if (EC == std::errc::no_lock_available)
364 return createFileError(
365 PathBuf, EC,
366 "CAS validation requires exclusive access but CAS was in use");
367 return createFileError(PathBuf, EC);
368 }
369 auto UnlockFD = make_scope_exit([&]() { unlockFileThreadSafe(LockFD); });
370
371 auto DBDirs = getAllDBDirs(RootPath);
372 if (!DBDirs)
373 return DBDirs.takeError();
374
375 for (StringRef DBDir : *DBDirs) {
377 sys::path::append(PathBuf, DBDir);
378 std::error_code EC;
379 int Attempt = 0, MaxAttempts = 100;
380 SmallString<128> GCPath;
381 for (; Attempt < MaxAttempts; ++Attempt) {
382 GCPath.assign(RootPath);
383 sys::path::append(GCPath, CorruptPrefix + std::to_string(Attempt) +
384 "." + DBDir);
385 EC = sys::fs::rename(PathBuf, GCPath);
386 // Darwin uses ENOTEMPTY. Linux may return either ENOTEMPTY or EEXIST.
388 break;
389 }
390 if (Attempt == MaxAttempts)
391 return createStringError(
392 EC, "rename " + PathBuf +
393 " failed: too many CAS directories awaiting pruning");
394 if (EC)
395 return createStringError(EC, "rename " + PathBuf + " to " + GCPath +
396 " failed: " + EC.message());
397 }
398 }
399
400 if (ValidationBootTime != BootTime) {
401 // Fix filename in case we have error to report.
404 if (std::error_code EC = sys::fs::resize_file(FD, 0))
405 return createFileError(PathBuf, EC);
406 raw_fd_ostream OS(FD, /*shouldClose=*/false);
407 OS.seek(0); // resize does not reset position
408 OS << BootTime << '\n';
409 if (OS.has_error())
410 return createFileError(PathBuf, OS.error());
411 }
412
414}
415
417UnifiedOnDiskCache::open(StringRef RootPath, std::optional<uint64_t> SizeLimit,
418 StringRef HashName, unsigned HashByteSize,
419 OnDiskGraphDB::FaultInPolicy FaultInPolicy) {
420 if (std::error_code EC = sys::fs::create_directories(RootPath))
421 return createFileError(RootPath, EC);
422
423 SmallString<256> PathBuf(RootPath);
424 sys::path::append(PathBuf, "lock");
425 int LockFD = -1;
426 if (std::error_code EC = sys::fs::openFileForReadWrite(
427 PathBuf, LockFD, sys::fs::CD_OpenAlways, sys::fs::OF_None))
428 return createFileError(PathBuf, EC);
429 assert(LockFD != -1);
430 // Locking the directory using shared lock, which will prevent other processes
431 // from creating a new chain (essentially while a \p UnifiedOnDiskCache
432 // instance holds a shared lock the storage for the primary directory will
433 // grow unrestricted).
434 if (std::error_code EC =
436 return createFileError(PathBuf, EC);
437
438 auto DBDirs = getAllDBDirs(RootPath);
439 if (!DBDirs)
440 return DBDirs.takeError();
441 if (DBDirs->empty())
442 DBDirs->push_back((Twine(DBDirPrefix) + "1").str());
443
444 assert(!DBDirs->empty());
445
446 /// If there is only one directory open databases on it. If there are 2 or
447 /// more directories, get the most recent directories and chain them, with the
448 /// most recent being the primary one. The remaining directories are unused
449 /// data than can be garbage-collected.
450 auto UniDB = std::unique_ptr<UnifiedOnDiskCache>(new UnifiedOnDiskCache());
451 std::unique_ptr<OnDiskGraphDB> UpstreamGraphDB;
452 std::unique_ptr<OnDiskKeyValueDB> UpstreamKVDB;
453 if (DBDirs->size() > 1) {
454 StringRef UpstreamDir = *(DBDirs->end() - 2);
455 PathBuf = RootPath;
456 sys::path::append(PathBuf, UpstreamDir);
457 if (Error E = OnDiskGraphDB::open(PathBuf, HashName, HashByteSize,
458 /*UpstreamDB=*/nullptr, FaultInPolicy)
459 .moveInto(UpstreamGraphDB))
460 return std::move(E);
461 if (Error E = OnDiskKeyValueDB::open(PathBuf, HashName, HashByteSize,
462 /*ValueName=*/"objectid",
463 /*ValueSize=*/sizeof(uint64_t))
464 .moveInto(UpstreamKVDB))
465 return std::move(E);
466 }
467
468 StringRef PrimaryDir = *(DBDirs->end() - 1);
469 PathBuf = RootPath;
470 sys::path::append(PathBuf, PrimaryDir);
471 std::unique_ptr<OnDiskGraphDB> PrimaryGraphDB;
472 if (Error E = OnDiskGraphDB::open(PathBuf, HashName, HashByteSize,
473 UpstreamGraphDB.get(), FaultInPolicy)
474 .moveInto(PrimaryGraphDB))
475 return std::move(E);
476 std::unique_ptr<OnDiskKeyValueDB> PrimaryKVDB;
477 // \p UnifiedOnDiskCache does manual chaining for key-value requests,
478 // including an extra translation step of the value during fault-in.
479 if (Error E =
480 OnDiskKeyValueDB::open(PathBuf, HashName, HashByteSize,
481 /*ValueName=*/"objectid",
482 /*ValueSize=*/sizeof(uint64_t), UniDB.get())
483 .moveInto(PrimaryKVDB))
484 return std::move(E);
485
486 UniDB->RootPath = RootPath;
487 UniDB->SizeLimit = SizeLimit.value_or(0);
488 UniDB->LockFD = LockFD;
489 UniDB->NeedsGarbageCollection = DBDirs->size() > 2;
490 UniDB->PrimaryDBDir = PrimaryDir;
491 UniDB->UpstreamGraphDB = std::move(UpstreamGraphDB);
492 UniDB->PrimaryGraphDB = std::move(PrimaryGraphDB);
493 UniDB->UpstreamKVDB = std::move(UpstreamKVDB);
494 UniDB->PrimaryKVDB = std::move(PrimaryKVDB);
495
496 return std::move(UniDB);
497}
498
499void UnifiedOnDiskCache::setSizeLimit(std::optional<uint64_t> SizeLimit) {
500 this->SizeLimit = SizeLimit.value_or(0);
501}
502
504 uint64_t TotalSize = getPrimaryStorageSize();
505 if (UpstreamGraphDB)
506 TotalSize += UpstreamGraphDB->getStorageSize();
507 if (UpstreamKVDB)
508 TotalSize += UpstreamKVDB->getStorageSize();
509 return TotalSize;
510}
511
512uint64_t UnifiedOnDiskCache::getPrimaryStorageSize() const {
513 return PrimaryGraphDB->getStorageSize() + PrimaryKVDB->getStorageSize();
514}
515
517 uint64_t CurSizeLimit = SizeLimit;
518 if (!CurSizeLimit)
519 return false;
520
521 // If the hard limit is beyond 85%, declare above limit and request clean up.
522 unsigned CurrentPercent =
523 std::max(PrimaryGraphDB->getHardStorageLimitUtilization(),
524 PrimaryKVDB->getHardStorageLimitUtilization());
525 if (CurrentPercent > 85)
526 return true;
527
528 // We allow each of the directories in the chain to reach up to half the
529 // intended size limit. Check whether the primary directory has exceeded half
530 // the limit or not, in order to decide whether we need to start a new chain.
531 //
532 // We could check the size limit against the sum of sizes of both the primary
533 // and upstream directories but then if the upstream is significantly larger
534 // than the intended limit, it would trigger a new chain to be created before
535 // the primary has reached its own limit. Essentially in such situation we
536 // prefer reclaiming the storage later in order to have more consistent cache
537 // hits behavior.
538 return (CurSizeLimit / 2) < getPrimaryStorageSize();
539}
540
541Error UnifiedOnDiskCache::close(bool CheckSizeLimit) {
542 if (LockFD == -1)
543 return Error::success(); // already closed.
544 auto CloseLock = make_scope_exit([&]() {
545 assert(LockFD >= 0);
547 sys::fs::closeFile(LockFile);
548 LockFD = -1;
549 });
550
551 bool ExceededSizeLimit = CheckSizeLimit ? hasExceededSizeLimit() : false;
552 UpstreamKVDB.reset();
553 PrimaryKVDB.reset();
554 UpstreamGraphDB.reset();
555 PrimaryGraphDB.reset();
556 if (std::error_code EC = unlockFileThreadSafe(LockFD))
557 return createFileError(RootPath, EC);
558
559 if (!ExceededSizeLimit)
560 return Error::success();
561
562 // The primary directory exceeded its intended size limit. Try to get an
563 // exclusive lock in order to create a new primary directory for next time
564 // this \p UnifiedOnDiskCache path is opened.
565
566 if (std::error_code EC = tryLockFileThreadSafe(
567 LockFD, std::chrono::milliseconds(0), sys::fs::LockKind::Exclusive)) {
568 if (EC == errc::no_lock_available)
569 return Error::success(); // couldn't get exclusive lock, give up.
570 return createFileError(RootPath, EC);
571 }
572 auto UnlockFile = make_scope_exit([&]() { unlockFileThreadSafe(LockFD); });
573
574 // Managed to get an exclusive lock which means there are no other open
575 // \p UnifiedOnDiskCache instances for the same path, so we can safely start a
576 // new primary directory. To start a new primary directory we just have to
577 // create a new empty directory with the next consecutive index; since this is
578 // an atomic operation we will leave the top-level directory in a consistent
579 // state even if the process dies during this code-path.
580
581 SmallString<256> PathBuf(RootPath);
582 raw_svector_ostream OS(PathBuf);
584 getNextDBDirName(PrimaryDBDir, OS);
585 if (std::error_code EC = sys::fs::create_directory(PathBuf))
586 return createFileError(PathBuf, EC);
587
588 NeedsGarbageCollection = true;
589 return Error::success();
590}
591
592UnifiedOnDiskCache::UnifiedOnDiskCache() = default;
593
595
597 auto DBDirs = getAllGarbageDirs(Path);
598 if (!DBDirs)
599 return DBDirs.takeError();
600
601 SmallString<256> PathBuf(Path);
602 for (StringRef UnusedSubDir : *DBDirs) {
603 sys::path::append(PathBuf, UnusedSubDir);
604 if (std::error_code EC = sys::fs::remove_directories(PathBuf))
605 return createFileError(PathBuf, EC);
607 }
608 return Error::success();
609}
610
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< uint64_t > getBootTime()
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:854
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.
Represents the result of a call to sys::fs::status().
Definition FileSystem.h:222
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.
@ 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:1174
@ 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:967
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:912
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 status(const Twine &path, file_status &result, bool follow=true)
Get file status as if by POSIX stat().
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:609
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:474
LLVM_ABI StringRef filename(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get filename.
Definition Path.cpp:577
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:456
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:1622
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:167
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.
std::error_code errnoAsErrorCode()
Helper to get errno as an std::error_code.
Definition Error.h:1240
void consumeError(Error Err)
Consume a Error without doing anything.
Definition Error.h:1083
@ Keep
No function return thunk.
Definition CodeGen.h:162