Skip to content

Commit 031a781

Browse files
[CAS] Use OnDiskOutputBackend to write outputs
Use a OnDiskOutputBackend to write cached outputs. Currently, the cached output is written to a FileOutputBuffer, which means if it is writing to an existing location, the existing file might be removed on creation of the buffer and create a window of invalid file before the output is commited. Using an ondisk output backend (default to atomic write) will make sure the file didn't get overwritten until the file is completed, thus the file is always valid. rdar://137080508
1 parent fe32f36 commit 031a781

File tree

1 file changed

+24
-22
lines changed

1 file changed

+24
-22
lines changed

clang/lib/Frontend/CompileJobCache.cpp

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -782,6 +782,7 @@ Expected<std::optional<int>> ObjectStoreCachingOutputs::replayCachedResult(
782782
DiagnosticsEngine &Diags = Clang.getDiagnostics();
783783
bool HasMissingOutput = false;
784784
std::optional<llvm::cas::ObjectProxy> SerialDiags;
785+
llvm::vfs::OnDiskOutputBackend Backend;
785786

786787
auto processOutput = [&](clang::cas::CompileJobCacheResult::Output O,
787788
std::optional<llvm::cas::ObjectProxy> Obj) -> Error {
@@ -815,47 +816,48 @@ Expected<std::optional<int>> ObjectStoreCachingOutputs::replayCachedResult(
815816

816817
bool IsOutputFile = O.Kind == OutputKind::MainOutput;
817818

818-
std::optional<StringRef> Contents;
819-
SmallString<50> ContentsStorage;
820819
if (IsOutputFile && ComputedJobNeedsReplay) {
821-
llvm::raw_svector_ostream OS(ContentsStorage);
820+
auto Output = Backend.createFile(Path);
821+
if (!Output)
822+
return Output.takeError();
822823
if (WriteOutputAsCASID)
823-
llvm::cas::writeCASIDBuffer(CAS.getID(O.Object), OS);
824+
llvm::cas::writeCASIDBuffer(CAS.getID(O.Object), *Output);
824825
else if (UseCASBackend) {
825826
// Replay by write out object file.
826827
// When the environmental variable is set, save the backend CASID for
827828
// analysis later.
828829
if (llvm::sys::Process::GetEnv("CLANG_CAS_BACKEND_SAVE_CASID_FILE")) {
829830
std::string CASIDPath = Path + ".casid";
830831
std::error_code EC;
831-
llvm::raw_fd_ostream IDOS(CASIDPath, EC);
832-
if (EC)
833-
return llvm::errorCodeToError(EC);
834-
writeCASIDBuffer(CAS.getID(O.Object), IDOS);
832+
auto IDOut = Backend.createFile(CASIDPath);
833+
if (!IDOut)
834+
return IDOut.takeError();
835+
writeCASIDBuffer(CAS.getID(O.Object), *IDOut);
836+
if (auto E = IDOut->keep())
837+
return E;
835838
}
836839
auto Schema = std::make_unique<llvm::mccasformats::v1::MCSchema>(CAS);
837-
if (auto E = Schema->serializeObjectFile(*Obj, OS))
840+
if (auto E = Schema->serializeObjectFile(*Obj, *Output))
838841
return E;
839842
}
840-
Contents = ContentsStorage;
841-
} else if (JustComputedResult) {
843+
return Output->keep();
844+
}
845+
846+
if (JustComputedResult)
842847
return Error::success(); // continue
843-
} else if (O.Kind == OutputKind::Dependencies) {
844-
llvm::raw_svector_ostream OS(ContentsStorage);
848+
849+
auto Output = Backend.createFile(Path);
850+
if (!Output)
851+
return Output.takeError();
852+
if (O.Kind == OutputKind::Dependencies) {
845853
if (auto E = CASDependencyCollector::replay(
846-
Clang.getDependencyOutputOpts(), CAS, *Obj, OS))
854+
Clang.getDependencyOutputOpts(), CAS, *Obj, *Output))
847855
return E;
848-
Contents = ContentsStorage;
849856
} else {
850-
Contents = Obj->getData();
857+
*Output << Obj->getData();
851858
}
852859

853-
std::unique_ptr<llvm::FileOutputBuffer> Output;
854-
if (Error E = llvm::FileOutputBuffer::create(Path, Contents->size())
855-
.moveInto(Output))
856-
return E;
857-
llvm::copy(*Contents, Output->getBufferStart());
858-
return Output->commit();
860+
return Output->keep();
859861
};
860862

861863
if (auto Err = Result.forEachLoadedOutput(processOutput))

0 commit comments

Comments
 (0)