LLVM: lib/CAS/UnifiedOnDiskCache.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

89#include

90

91#if __has_include(<sys/sysctl.h>)

92#include <sys/sysctl.h>

93#endif

94

95using namespace llvm;

98

99

100

101

103

106

112

115

117 static_assert(ValBytes.size() == sizeof(ID.getOpaqueData()));

119 return ValBytes;

120}

121

124 assert(UpstreamGraphDB);

125 assert(UpstreamKVDB);

126

127 std::optional<ArrayRef> UpstreamValue;

128 if (Error E = UpstreamKVDB->get(Key).moveInto(UpstreamValue))

129 return std::move(E);

130 if (!UpstreamValue)

131 return std::nullopt;

132

133

134

135

137 auto PrimaryID =

138 PrimaryGraphDB->getReference(UpstreamGraphDB->getDigest(UpstreamID));

140 return PrimaryID.takeError();

142}

143

144

145

146

149 struct DBDir {

151 std::string Name;

152 };

154

155 std::error_code EC;

157 DirI.increment(EC)) {

159 continue;

162 FoundDBDirs.push_back({0, std::string(SubDir)});

163 continue;

164 }

166 continue;

170 "unexpected directory " + DirI->path());

171 FoundDBDirs.push_back({Order, std::string(SubDir)});

172 }

173 if (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, true);

188 if (!DBDirs)

189 return DBDirs.takeError();

190

191

192

193

194 for (unsigned Keep = 2; Keep > 0 && !DBDirs->empty(); --Keep) {

197 break;

198 DBDirs->pop_back();

199 }

200 return *DBDirs;

201}

202

203

204

213

215 bool CheckHash) {

217 if (CheckHash)

218 Args.push_back("-check-hash");

219

221 int StdErrFD = -1;

223 "llvm-cas-validate-stderr", "txt", StdErrFD, StdErrPath,

227

228 std::optionalllvm::StringRef Redirects[] = {

229 {""},

230 {""},

231 StdErrPath.str(),

232 };

233

234 std::string ErrMsg;

235 int Result =

236 sys::ExecuteAndWait(LLVMCasBinary, Args, std::nullopt, Redirects,

237 120, 0, &ErrMsg);

238

239 if (Result == -1)

241 ErrMsg);

242 if (Result != 0) {

244 if (!ErrMsg.empty()) {

245 Err += ": ";

246 Err += ErrMsg;

247 }

249 if (StdErrBuf && !(*StdErrBuf)->getBuffer().empty()) {

250 Err += ": ";

251 Err += (*StdErrBuf)->getBuffer();

252 }

254 }

256}

257

259 unsigned HashByteSize, bool CheckHash) {

260 std::shared_ptr UniDB;

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;

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

287

291 return Status.getLastModificationTime().time_since_epoch().count();

292#else

294#endif

295}

296

299 bool CheckHash, bool AllowRecovery, bool ForceValidation,

300 std::optional LLVMCasBinaryPath) {

303

306 int FD = -1;

311

314

318

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)

332 return std::move(E);

333

334 if (ValidationBootTime == BootTime && !ForceValidation)

336

337

338 bool NeedsRecovery = false;

340 LLVMCasBinaryPath

343 CheckHash)) {

344 if (AllowRecovery) {

346 NeedsRecovery = true;

347 } else {

348 return std::move(E);

349 }

350 }

351

352 if (NeedsRecovery) {

355

356 int LockFD = -1;

363 if (EC == std::errc::no_lock_available)

365 PathBuf, EC,

366 "CAS validation requires exclusive access but CAS was in use");

368 }

370

372 if (!DBDirs)

373 return DBDirs.takeError();

374

375 for (StringRef DBDir : *DBDirs) {

378 std::error_code EC;

379 int Attempt = 0, MaxAttempts = 100;

381 for (; Attempt < MaxAttempts; ++Attempt) {

382 GCPath.assign(RootPath);

384 "." + DBDir);

386

388 break;

389 }

390 if (Attempt == MaxAttempts)

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

407 OS.seek(0);

408 OS << BootTime << '\n';

411 }

412

414}

415

418 StringRef HashName, unsigned HashByteSize,

422

425 int LockFD = -1;

429 assert(LockFD != -1);

430

431

432

433

434 if (std::error_code EC =

437

439 if (!DBDirs)

440 return DBDirs.takeError();

441 if (DBDirs->empty())

443

444 assert(!DBDirs->empty());

445

446

447

448

449

450 auto UniDB = std::unique_ptr(new UnifiedOnDiskCache());

451 std::unique_ptr UpstreamGraphDB;

452 std::unique_ptr UpstreamKVDB;

453 if (DBDirs->size() > 1) {

454 StringRef UpstreamDir = *(DBDirs->end() - 2);

455 PathBuf = RootPath;

458 nullptr, FaultInPolicy)

459 .moveInto(UpstreamGraphDB))

460 return std::move(E);

462 "objectid",

463 sizeof(uint64_t))

464 .moveInto(UpstreamKVDB))

465 return std::move(E);

466 }

467

468 StringRef PrimaryDir = *(DBDirs->end() - 1);

469 PathBuf = RootPath;

471 std::unique_ptr PrimaryGraphDB;

473 UpstreamGraphDB.get(), FaultInPolicy)

474 .moveInto(PrimaryGraphDB))

475 return std::move(E);

476 std::unique_ptr PrimaryKVDB;

477

478

481 "objectid",

482 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

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

522 unsigned CurrentPercent =

523 std::max(PrimaryGraphDB->getHardStorageLimitUtilization(),

524 PrimaryKVDB->getHardStorageLimitUtilization());

525 if (CurrentPercent > 85)

526 return true;

527

528

529

530

531

532

533

534

535

536

537

538 return (CurSizeLimit / 2) < getPrimaryStorageSize();

539}

540

542 if (LockFD == -1)

548 LockFD = -1;

549 });

550

552 UpstreamKVDB.reset();

553 PrimaryKVDB.reset();

554 UpstreamGraphDB.reset();

555 PrimaryGraphDB.reset();

558

559 if (!ExceededSizeLimit)

561

562

563

564

565

569 return Error::success();

571 }

573

574

575

576

577

578

579

580

587

588 NeedsGarbageCollection = true;

590}

591

592UnifiedOnDiskCache::UnifiedOnDiskCache() = default;

593

595

598 if (!DBDirs)

599 return DBDirs.takeError();

600

602 for (StringRef UnusedSubDir : *DBDirs) {

607 }

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)

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 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.

static constexpr StringLiteral DBDirPrefix

FIXME: When the version of DBDirPrefix is bumped up we need to figure out how to handle the leftover ...

Definition UnifiedOnDiskCache.cpp:102

static Error validateInProcess(StringRef RootPath, StringRef HashName, unsigned HashByteSize, bool CheckHash)

Definition UnifiedOnDiskCache.cpp:258

static Expected< SmallVector< std::string, 4 > > getAllGarbageDirs(StringRef Path)

Definition UnifiedOnDiskCache.cpp:186

static constexpr StringLiteral ValidationFilename

Definition UnifiedOnDiskCache.cpp:104

static constexpr StringLiteral CorruptPrefix

Definition UnifiedOnDiskCache.cpp:105

static void getNextDBDirName(StringRef DBDir, llvm::raw_ostream &OS)

Definition UnifiedOnDiskCache.cpp:205

static Error validateOutOfProcess(StringRef LLVMCasBinary, StringRef RootPath, bool CheckHash)

Definition UnifiedOnDiskCache.cpp:214

static Expected< uint64_t > getBootTime()

Definition UnifiedOnDiskCache.cpp:274

static Expected< SmallVector< std::string, 4 > > getAllDBDirs(StringRef Path, bool IncludeCorrupt=false)

Definition UnifiedOnDiskCache.cpp:148

ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...

Lightweight error class with error context and mandatory checking.

static ErrorSuccess success()

Create a success value.

Tagged union holding either a T or a Error.

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...

void assign(StringRef RHS)

Assign from a StringRef.

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...

StringRef - Represent a constant reference to a string, i.e.

bool getAsInteger(unsigned Radix, T &Result) const

Parse the current string as an integer of the specified radix.

constexpr StringRef substr(size_t Start, size_t N=npos) const

Return a reference to the substring from [Start, Start + N).

bool starts_with(StringRef Prefix) const

Check if this string starts with the given Prefix.

Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...

LLVM Value Representation.

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

Definition UnifiedOnDiskCache.cpp:503

static LLVM_ABI_FOR_TEST ValueBytes getValueFromObjectID(ObjectID ID)

Definition UnifiedOnDiskCache.cpp:114

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.

Definition UnifiedOnDiskCache.cpp:417

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.

Definition UnifiedOnDiskCache.cpp:541

static LLVM_ABI_FOR_TEST ObjectID getObjectIDFromValue(ArrayRef< char > Value)

Helper function to convert the value stored in KeyValueDB and ObjectID.

Definition UnifiedOnDiskCache.cpp:107

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.

Definition UnifiedOnDiskCache.cpp:297

LLVM_ABI_FOR_TEST bool hasExceededSizeLimit() const

Definition UnifiedOnDiskCache.cpp:516

LLVM_ABI_FOR_TEST ~UnifiedOnDiskCache()

Definition UnifiedOnDiskCache.cpp:594

std::array< char, sizeof(uint64_t)> ValueBytes

Error collectGarbage()

Remove unused data from the current UnifiedOnDiskCache.

Definition UnifiedOnDiskCache.cpp:611

LLVM_ABI_FOR_TEST void setSizeLimit(std::optional< uint64_t > SizeLimit)

Set the size for limiting growth.

Definition UnifiedOnDiskCache.cpp:499

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.

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().

unsigned ID

LLVM IR allows to use arbitrary numbers as calling convention identifiers.

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)

void write64le(void *P, uint64_t V)

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.

@ OF_Text

The file should be opened in text mode on platforms like z/OS that make this distinction.

@ CD_OpenAlways

CD_OpenAlways - When opening a file:

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.

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.

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.

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.

LLVM_ABI void remove_filename(SmallVectorImpl< char > &path, Style style=Style::native)

Remove the last component from path unless it is the root dir.

LLVM_ABI StringRef filename(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)

Get filename.

LLVM_ABI void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")

Append to path.

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.

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.

detail::scope_exit< std::decay_t< Callable > > make_scope_exit(Callable &&F)

LLVM_ABI std::error_code inconvertibleErrorCode()

The value returned by this function can be returned from convertToErrorCode for Error values where no...

testing::Matcher< const detail::ErrorHolder & > Failed()

Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)

Create formatted StringError object.

void sort(IteratorTy Start, IteratorTy End)

LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)

FunctionAddr VTableAddr Count

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.

void consumeError(Error Err)

Consume a Error without doing anything.

@ Keep

No function return thunk.