[llvm] [llvm/CAS] Add file-based APIs to `OnDiskGraphDB` (PR #179782)
Argyrios Kyrtzidis via llvm-commits
llvm-commits at lists.llvm.org
Wed Feb 4 14:50:55 PST 2026
================
@@ -1567,6 +1632,138 @@ Error OnDiskGraphDB::store(ObjectID ID, ArrayRef<ObjectID> Refs,
return Error::success();
}
+Error OnDiskGraphDB::storeFile(ObjectID ID, StringRef FilePath,
+ bool AcceptingOwnership) {
+ return storeFile(ID, FilePath, AcceptingOwnership,
+ /*ImportKind=*/std::nullopt);
+}
+
+Error OnDiskGraphDB::storeFile(
+ ObjectID ID, StringRef FilePath, bool AcceptingOwnership,
+ std::optional<InternalUpstreamImportKind> ImportKind) {
+ uint64_t FileSize;
+ if (std::error_code EC = sys::fs::file_size(FilePath, FileSize))
+ return errorCodeToError(EC);
+
+ if (FileSize <= TrieRecord::MaxEmbeddedSize) {
+ auto Buf = MemoryBuffer::getFile(FilePath);
+ if (!Buf)
+ return errorCodeToError(Buf.getError());
+ if (Error E =
+ store(ID, {}, arrayRefFromStringRef<char>((*Buf)->getBuffer())))
+ return E;
+ if (AcceptingOwnership)
+ if (std::error_code EC = sys::fs::remove(FilePath))
+ return errorCodeToError(EC);
+ return Error::success();
+ }
+
+ auto I = getIndexProxyFromRef(getInternalRef(ID));
+ if (LLVM_UNLIKELY(!I))
+ return I.takeError();
+
+ // Early return in case the node exists.
+ {
+ TrieRecord::Data Existing = I->Ref.load();
+ if (Existing.SK != TrieRecord::StorageKind::Unknown) {
+ if (AcceptingOwnership)
+ if (std::error_code EC = sys::fs::remove(FilePath))
+ return errorCodeToError(EC);
+ return Error::success();
+ }
+ }
+
+ StringRef FromPath;
+ SmallString<256> TmpPath;
+
+ auto RemoveTmpFile = scope_exit([&TmpPath] {
+ if (!TmpPath.empty())
+ sys::fs::remove(TmpPath);
+ });
+
+ if (AcceptingOwnership) {
+ FromPath = FilePath;
+ } else {
+ // \c clonefile requires that the destination path doesn't exist. We create
+ // a "placeholder" temporary file, then modify its path a bit and use that
+ // for \c clonefile to write to.
+ SmallString<256> UniqueTmpPath;
+ if (std::error_code EC =
+ sys::fs::createUniqueFile(RootPath + "/tmp.%%%%%%%", UniqueTmpPath))
+ return errorCodeToError(EC);
+ auto RemoveUniqueFile =
+ scope_exit([&UniqueTmpPath] { sys::fs::remove(UniqueTmpPath); });
+ TmpPath = UniqueTmpPath;
+ TmpPath += 'c'; // modify so that there's no file at that path.
+ // \c copy_file will use \c clonefile when applicable.
+ if (std::error_code EC = sys::fs::copy_file(FilePath, TmpPath))
+ return errorCodeToError(EC);
+ FromPath = TmpPath;
+ }
+
+ TrieRecord::StorageKind SK;
+ if (ImportKind.has_value()) {
+ // Importing the file from upstream, the nul is already added if necessary.
+ switch (*ImportKind) {
+ case InternalUpstreamImportKind::Leaf:
+ SK = TrieRecord::StorageKind::StandaloneLeaf;
+ break;
+ case InternalUpstreamImportKind::Leaf0:
+ SK = TrieRecord::StorageKind::StandaloneLeaf0;
+ break;
+ }
+ } else {
+ bool Leaf0 = isAligned(Align(getPageSize()), FileSize);
+ SK = Leaf0 ? TrieRecord::StorageKind::StandaloneLeaf0
+ : TrieRecord::StorageKind::StandaloneLeaf;
+
+ if (Leaf0) {
+ // Add a nul byte at the end.
----------------
akyrtzi wrote:
When not taking ownership this modifies the new temporary file.
https://github.com/llvm/llvm-project/pull/179782
More information about the llvm-commits
mailing list