Skip to content

Commit d93fb41

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 (cherry picked from commit 031a781)
1 parent b46c5f7 commit d93fb41

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
@@ -752,6 +752,7 @@ Expected<std::optional<int>> ObjectStoreCachingOutputs::replayCachedResult(
752752
DiagnosticsEngine &Diags = Clang.getDiagnostics();
753753
bool HasMissingOutput = false;
754754
std::optional<llvm::cas::ObjectProxy> SerialDiags;
755+
llvm::vfs::OnDiskOutputBackend Backend;
755756

756757
auto processOutput = [&](clang::cas::CompileJobCacheResult::Output O,
757758
std::optional<llvm::cas::ObjectProxy> Obj) -> Error {
@@ -785,47 +786,48 @@ Expected<std::optional<int>> ObjectStoreCachingOutputs::replayCachedResult(
785786

786787
bool IsOutputFile = O.Kind == OutputKind::MainOutput;
787788

788-
std::optional<StringRef> Contents;
789-
SmallString<50> ContentsStorage;
790789
if (IsOutputFile && ComputedJobNeedsReplay) {
791-
llvm::raw_svector_ostream OS(ContentsStorage);
790+
auto Output = Backend.createFile(Path);
791+
if (!Output)
792+
return Output.takeError();
792793
if (WriteOutputAsCASID)
793-
llvm::cas::writeCASIDBuffer(CAS.getID(O.Object), OS);
794+
llvm::cas::writeCASIDBuffer(CAS.getID(O.Object), *Output);
794795
else if (UseCASBackend) {
795796
// Replay by write out object file.
796797
// When the environmental variable is set, save the backend CASID for
797798
// analysis later.
798799
if (llvm::sys::Process::GetEnv("CLANG_CAS_BACKEND_SAVE_CASID_FILE")) {
799800
std::string CASIDPath = Path + ".casid";
800801
std::error_code EC;
801-
llvm::raw_fd_ostream IDOS(CASIDPath, EC);
802-
if (EC)
803-
return llvm::errorCodeToError(EC);
804-
writeCASIDBuffer(CAS.getID(O.Object), IDOS);
802+
auto IDOut = Backend.createFile(CASIDPath);
803+
if (!IDOut)
804+
return IDOut.takeError();
805+
writeCASIDBuffer(CAS.getID(O.Object), *IDOut);
806+
if (auto E = IDOut->keep())
807+
return E;
805808
}
806809
auto Schema = std::make_unique<llvm::mccasformats::v1::MCSchema>(CAS);
807-
if (auto E = Schema->serializeObjectFile(*Obj, OS))
810+
if (auto E = Schema->serializeObjectFile(*Obj, *Output))
808811
return E;
809812
}
810-
Contents = ContentsStorage;
811-
} else if (JustComputedResult) {
813+
return Output->keep();
814+
}
815+
816+
if (JustComputedResult)
812817
return Error::success(); // continue
813-
} else if (O.Kind == OutputKind::Dependencies) {
814-
llvm::raw_svector_ostream OS(ContentsStorage);
818+
819+
auto Output = Backend.createFile(Path);
820+
if (!Output)
821+
return Output.takeError();
822+
if (O.Kind == OutputKind::Dependencies) {
815823
if (auto E = CASDependencyCollector::replay(
816-
Clang.getDependencyOutputOpts(), CAS, *Obj, OS))
824+
Clang.getDependencyOutputOpts(), CAS, *Obj, *Output))
817825
return E;
818-
Contents = ContentsStorage;
819826
} else {
820-
Contents = Obj->getData();
827+
*Output << Obj->getData();
821828
}
822829

823-
std::unique_ptr<llvm::FileOutputBuffer> Output;
824-
if (Error E = llvm::FileOutputBuffer::create(Path, Contents->size())
825-
.moveInto(Output))
826-
return E;
827-
llvm::copy(*Contents, Output->getBufferStart());
828-
return Output->commit();
830+
return Output->keep();
829831
};
830832

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

0 commit comments

Comments
 (0)