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

91using namespace llvm;

94

95

96

97

99

102

108

111

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

115 return ValBytes;

116}

117

120 assert(UpstreamGraphDB);

121 assert(UpstreamKVDB);

122

123 std::optional<ArrayRef> UpstreamValue;

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

125 return std::move(E);

126 if (!UpstreamValue)

127 return std::nullopt;

128

129

130

131

133 auto PrimaryID =

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

136 return PrimaryID.takeError();

138}

139

140

141

142

145 struct DBDir {

147 std::string Name;

148 };

150

151 std::error_code EC;

153 DirI.increment(EC)) {

155 continue;

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

159 continue;

160 }

162 continue;

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

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

168 }

169 if (EC)

171

172 llvm::sort(FoundDBDirs, [](const DBDir &LHS, const DBDir &RHS) -> bool {

173 return LHS.Order < RHS.Order;

174 });

175

177 for (DBDir &Dir : FoundDBDirs)

178 DBDirs.push_back(std::move(Dir.Name));

179 return DBDirs;

180}

181

183 auto DBDirs = getAllDBDirs(Path, true);

184 if (!DBDirs)

185 return DBDirs.takeError();

186

187

188

189

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

193 break;

194 DBDirs->pop_back();

195 }

196 return *DBDirs;

197}

198

199

200

209

211 bool CheckHash) {

213 if (CheckHash)

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

215

217 int StdErrFD = -1;

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

223

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

225 {""},

226 {""},

227 StdErrPath.str(),

228 };

229

230 std::string ErrMsg;

231 int Result =

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

233 120, 0, &ErrMsg);

234

235 if (Result == -1)

237 ErrMsg);

238 if (Result != 0) {

240 if (!ErrMsg.empty()) {

241 Err += ": ";

242 Err += ErrMsg;

243 }

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

246 Err += ": ";

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

248 }

250 }

252}

253

255 unsigned HashByteSize, bool CheckHash) {

256 std::shared_ptr UniDB;

258 HashByteSize)

259 .moveInto(UniDB))

260 return E;

262 if (Error E = CAS->validate(CheckHash))

263 return E;

265 if (Error E = Cache->validate())

266 return E;

268}

269

272 bool CheckHash, bool AllowRecovery, bool ForceValidation,

273 std::optional LLVMCasBinaryPath) {

276

279 int FD = -1;

284

287

291

295

296 uint64_t ValidationBootTime = 0;

297 if (!Bytes.empty() &&

298 StringRef(Bytes).trim().getAsInteger(10, ValidationBootTime))

300 "expected integer");

301

302 static uint64_t BootTime = 0;

303 if (BootTime == 0)

305 return std::move(E);

306

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

309

310

311 bool NeedsRecovery = false;

313 LLVMCasBinaryPath

316 CheckHash)) {

317 if (AllowRecovery) {

319 NeedsRecovery = true;

320 } else {

321 return std::move(E);

322 }

323 }

324

325 if (NeedsRecovery) {

328

329 int LockFD = -1;

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

338 PathBuf, EC,

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

341 }

343

345 if (!DBDirs)

346 return DBDirs.takeError();

347

348 for (StringRef DBDir : *DBDirs) {

351 std::error_code EC;

352 int Attempt = 0, MaxAttempts = 100;

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

355 GCPath.assign(RootPath);

357 "." + DBDir);

359

361 break;

362 }

363 if (Attempt == MaxAttempts)

365 EC, "rename " + PathBuf +

366 " failed: too many CAS directories awaiting pruning");

367 if (EC)

368 return createStringError(EC, "rename " + PathBuf + " to " + GCPath +

369 " failed: " + EC.message());

370 }

371 }

372

373 if (ValidationBootTime != BootTime) {

374

380 OS.seek(0);

381 OS << BootTime << '\n';

384 }

385

387}

388

391 StringRef HashName, unsigned HashByteSize,

395

398 int LockFD = -1;

402 assert(LockFD != -1);

403

404

405

406

407 if (std::error_code EC =

410

412 if (!DBDirs)

413 return DBDirs.takeError();

414 if (DBDirs->empty())

416

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

418

419

420

421

422

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

424 std::unique_ptr UpstreamGraphDB;

425 std::unique_ptr UpstreamKVDB;

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

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

428 PathBuf = RootPath;

431 nullptr, FaultInPolicy)

432 .moveInto(UpstreamGraphDB))

433 return std::move(E);

435 "objectid",

436 sizeof(uint64_t))

437 .moveInto(UpstreamKVDB))

438 return std::move(E);

439 }

440

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

442 PathBuf = RootPath;

444 std::unique_ptr PrimaryGraphDB;

446 UpstreamGraphDB.get(), FaultInPolicy)

447 .moveInto(PrimaryGraphDB))

448 return std::move(E);

449 std::unique_ptr PrimaryKVDB;

450

451

454 "objectid",

455 sizeof(uint64_t), UniDB.get())

456 .moveInto(PrimaryKVDB))

457 return std::move(E);

458

459 UniDB->RootPath = RootPath;

460 UniDB->SizeLimit = SizeLimit.value_or(0);

461 UniDB->LockFD = LockFD;

462 UniDB->NeedsGarbageCollection = DBDirs->size() > 2;

463 UniDB->PrimaryDBDir = PrimaryDir;

464 UniDB->UpstreamGraphDB = std::move(UpstreamGraphDB);

465 UniDB->PrimaryGraphDB = std::move(PrimaryGraphDB);

466 UniDB->UpstreamKVDB = std::move(UpstreamKVDB);

467 UniDB->PrimaryKVDB = std::move(PrimaryKVDB);

468

469 return std::move(UniDB);

470}

471

473 this->SizeLimit = SizeLimit.value_or(0);

474}

475

477 uint64_t TotalSize = getPrimaryStorageSize();

478 if (UpstreamGraphDB)

479 TotalSize += UpstreamGraphDB->getStorageSize();

480 if (UpstreamKVDB)

481 TotalSize += UpstreamKVDB->getStorageSize();

482 return TotalSize;

483}

484

485uint64_t UnifiedOnDiskCache::getPrimaryStorageSize() const {

486 return PrimaryGraphDB->getStorageSize() + PrimaryKVDB->getStorageSize();

487}

488

490 uint64_t CurSizeLimit = SizeLimit;

491 if (!CurSizeLimit)

492 return false;

493

494

495 unsigned CurrentPercent =

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

497 PrimaryKVDB->getHardStorageLimitUtilization());

498 if (CurrentPercent > 85)

499 return true;

500

501

502

503

504

505

506

507

508

509

510

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

512}

513

515 if (LockFD == -1)

521 LockFD = -1;

522 });

523

525 UpstreamKVDB.reset();

526 PrimaryKVDB.reset();

527 UpstreamGraphDB.reset();

528 PrimaryGraphDB.reset();

531

532 if (!ExceededSizeLimit)

534

535

536

537

538

542 return Error::success();

544 }

546

547

548

549

550

551

552

553

560

561 NeedsGarbageCollection = true;

563}

564

565UnifiedOnDiskCache::UnifiedOnDiskCache() = default;

566

568

571 if (!DBDirs)

572 return DBDirs.takeError();

573

575 for (StringRef UnusedSubDir : *DBDirs) {

580 }

582}

583

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:98

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

Definition UnifiedOnDiskCache.cpp:254

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

Definition UnifiedOnDiskCache.cpp:182

static constexpr StringLiteral ValidationFilename

Definition UnifiedOnDiskCache.cpp:100

static constexpr StringLiteral CorruptPrefix

Definition UnifiedOnDiskCache.cpp:101

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

Definition UnifiedOnDiskCache.cpp:201

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

Definition UnifiedOnDiskCache.cpp:210

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

Definition UnifiedOnDiskCache.cpp:144

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:476

static LLVM_ABI_FOR_TEST ValueBytes getValueFromObjectID(ObjectID ID)

Definition UnifiedOnDiskCache.cpp:110

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:390

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:514

static LLVM_ABI_FOR_TEST ObjectID getObjectIDFromValue(ArrayRef< char > Value)

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

Definition UnifiedOnDiskCache.cpp:103

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:270

LLVM_ABI_FOR_TEST bool hasExceededSizeLimit() const

Definition UnifiedOnDiskCache.cpp:489

LLVM_ABI_FOR_TEST ~UnifiedOnDiskCache()

Definition UnifiedOnDiskCache.cpp:567

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

Error collectGarbage()

Remove unused data from the current UnifiedOnDiskCache.

Definition UnifiedOnDiskCache.cpp:584

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

Set the size for limiting growth.

Definition UnifiedOnDiskCache.cpp:472

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.

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.

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)

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

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.

void consumeError(Error Err)

Consume a Error without doing anything.

@ Keep

No function return thunk.