[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