summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Korous <jkorous@apple.com>2019-09-13 20:08:27 +0000
committerJan Korous <jkorous@apple.com>2019-09-13 20:08:27 +0000
commitf69c91780fbb0e9c0e95f70a079f578efdca0bfa (patch)
tree8c22ed25e585979a3fda35911273cf1e62de3707
parentc6ffefd2d1a95b7312741fbd3a9972e5f918173b (diff)
downloadbcm5719-llvm-f69c91780fbb0e9c0e95f70a079f578efdca0bfa.tar.gz
bcm5719-llvm-f69c91780fbb0e9c0e95f70a079f578efdca0bfa.zip
[Support] Add overload writeFileAtomically(std::function Writer)
Differential Revision: https://reviews.llvm.org/D67424 llvm-svn: 371890
-rw-r--r--clang-tools-extra/clangd/index/BackgroundIndexStorage.cpp38
-rw-r--r--clang/lib/Frontend/ASTUnit.cpp24
-rw-r--r--clang/lib/Serialization/GlobalModuleIndex.cpp37
-rw-r--r--lldb/tools/lldb-server/lldb-platform.cpp50
-rw-r--r--llvm/include/llvm/Support/FileUtilities.h31
-rw-r--r--llvm/lib/LTO/ThinLTOCodeGenerator.cpp32
-rw-r--r--llvm/lib/Support/FileUtilities.cpp63
7 files changed, 145 insertions, 130 deletions
diff --git a/clang-tools-extra/clangd/index/BackgroundIndexStorage.cpp b/clang-tools-extra/clangd/index/BackgroundIndexStorage.cpp
index 86c73ff7420..48510e11e84 100644
--- a/clang-tools-extra/clangd/index/BackgroundIndexStorage.cpp
+++ b/clang-tools-extra/clangd/index/BackgroundIndexStorage.cpp
@@ -18,6 +18,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/FileUtilities.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include <functional>
@@ -35,34 +36,6 @@ std::string getShardPathFromFilePath(llvm::StringRef ShardRoot,
return ShardRootSS.str();
}
-llvm::Error
-writeAtomically(llvm::StringRef OutPath,
- llvm::function_ref<void(llvm::raw_ostream &)> Writer) {
- // Write to a temporary file first.
- llvm::SmallString<128> TempPath;
- int FD;
- auto EC =
- llvm::sys::fs::createUniqueFile(OutPath + ".tmp.%%%%%%%%", FD, TempPath);
- if (EC)
- return llvm::errorCodeToError(EC);
- // Make sure temp file is destroyed on failure.
- auto RemoveOnFail =
- llvm::make_scope_exit([TempPath] { llvm::sys::fs::remove(TempPath); });
- llvm::raw_fd_ostream OS(FD, /*shouldClose=*/true);
- Writer(OS);
- OS.close();
- if (OS.has_error())
- return llvm::errorCodeToError(OS.error());
- // Then move to real location.
- EC = llvm::sys::fs::rename(TempPath, OutPath);
- if (EC)
- return llvm::errorCodeToError(EC);
- // If everything went well, we already moved the file to another name. So
- // don't delete the file, as the name might be taken by another file.
- RemoveOnFail.release();
- return llvm::ErrorSuccess();
-}
-
// Uses disk as a storage for index shards. Creates a directory called
// ".clangd/index/" under the path provided during construction.
class DiskBackedIndexStorage : public BackgroundIndexStorage {
@@ -100,9 +73,12 @@ public:
llvm::Error storeShard(llvm::StringRef ShardIdentifier,
IndexFileOut Shard) const override {
- return writeAtomically(
- getShardPathFromFilePath(DiskShardRoot, ShardIdentifier),
- [&Shard](llvm::raw_ostream &OS) { OS << Shard; });
+ auto ShardPath = getShardPathFromFilePath(DiskShardRoot, ShardIdentifier);
+ return llvm::writeFileAtomically(ShardPath + ".tmp.%%%%%%%%", ShardPath,
+ [&Shard](llvm::raw_ostream &OS) {
+ OS << Shard;
+ return llvm::Error::success();
+ });
}
};
diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp
index 35348ffe13b..f5e291b7fe1 100644
--- a/clang/lib/Frontend/ASTUnit.cpp
+++ b/clang/lib/Frontend/ASTUnit.cpp
@@ -84,6 +84,7 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/FileUtilities.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/VirtualFileSystem.h"
@@ -2301,26 +2302,19 @@ bool ASTUnit::Save(StringRef File) {
SmallString<128> TempPath;
TempPath = File;
TempPath += "-%%%%%%%%";
- int fd;
- if (llvm::sys::fs::createUniqueFile(TempPath, fd, TempPath))
- return true;
-
// FIXME: Can we somehow regenerate the stat cache here, or do we need to
// unconditionally create a stat cache when we parse the file?
- llvm::raw_fd_ostream Out(fd, /*shouldClose=*/true);
-
- serialize(Out);
- Out.close();
- if (Out.has_error()) {
- Out.clear_error();
- return true;
- }
- if (llvm::sys::fs::rename(TempPath, File)) {
- llvm::sys::fs::remove(TempPath);
+ if (llvm::Error Err = llvm::writeFileAtomically(
+ TempPath, File, [this](llvm::raw_ostream &Out) {
+ return serialize(Out) ? llvm::make_error<llvm::StringError>(
+ "ASTUnit serialization failed",
+ llvm::inconvertibleErrorCode())
+ : llvm::Error::success();
+ })) {
+ consumeError(std::move(Err));
return true;
}
-
return false;
}
diff --git a/clang/lib/Serialization/GlobalModuleIndex.cpp b/clang/lib/Serialization/GlobalModuleIndex.cpp
index 1833ebbdc84..54ab17681ee 100644
--- a/clang/lib/Serialization/GlobalModuleIndex.cpp
+++ b/clang/lib/Serialization/GlobalModuleIndex.cpp
@@ -10,7 +10,6 @@
//
//===----------------------------------------------------------------------===//
-
#include "ASTReaderInternals.h"
#include "clang/Basic/FileManager.h"
#include "clang/Lex/HeaderSearch.h"
@@ -21,10 +20,12 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Bitstream/BitstreamReader.h"
#include "llvm/Bitstream/BitstreamWriter.h"
#include "llvm/Support/DJB.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/FileUtilities.h"
#include "llvm/Support/LockFileManager.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/OnDiskHashTable.h"
@@ -912,37 +913,9 @@ GlobalModuleIndex::writeIndex(FileManager &FileMgr,
"failed writing index");
}
- // Write the global index file to a temporary file.
- llvm::SmallString<128> IndexTmpPath;
- int TmpFD;
- if (llvm::sys::fs::createUniqueFile(IndexPath + "-%%%%%%%%", TmpFD,
- IndexTmpPath))
- return llvm::createStringError(std::errc::io_error,
- "failed creating unique file");
-
- // Open the temporary global index file for output.
- llvm::raw_fd_ostream Out(TmpFD, true);
- if (Out.has_error())
- return llvm::createStringError(Out.error(), "failed outputting to stream");
-
- // Write the index.
- Out.write(OutputBuffer.data(), OutputBuffer.size());
- Out.close();
- if (Out.has_error())
- return llvm::createStringError(Out.error(), "failed writing to stream");
-
- // Remove the old index file. It isn't relevant any more.
- llvm::sys::fs::remove(IndexPath);
-
- // Rename the newly-written index file to the proper name.
- if (std::error_code Err = llvm::sys::fs::rename(IndexTmpPath, IndexPath)) {
- // Remove the file on failure, don't check whether removal succeeded.
- llvm::sys::fs::remove(IndexTmpPath);
- return llvm::createStringError(Err, "failed renaming file \"%s\" to \"%s\"",
- IndexTmpPath.c_str(), IndexPath.c_str());
- }
-
- return llvm::Error::success();
+ return llvm::writeFileAtomically(
+ (IndexPath + "-%%%%%%%%").str(), IndexPath,
+ llvm::StringRef(OutputBuffer.data(), OutputBuffer.size()));
}
namespace {
diff --git a/lldb/tools/lldb-server/lldb-platform.cpp b/lldb/tools/lldb-server/lldb-platform.cpp
index ee438da07fe..c837eea32cb 100644
--- a/lldb/tools/lldb-server/lldb-platform.cpp
+++ b/lldb/tools/lldb-server/lldb-platform.cpp
@@ -22,6 +22,7 @@
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FileUtilities.h"
+#include "llvm/Support/raw_ostream.h"
#include "Acceptor.h"
#include "LLDBServerUtilities.h"
@@ -103,29 +104,34 @@ static Status save_socket_id_to_file(const std::string &socket_id,
llvm::SmallString<64> temp_file_path;
temp_file_spec.AppendPathComponent("port-file.%%%%%%");
- int FD;
- auto err_code = llvm::sys::fs::createUniqueFile(temp_file_spec.GetPath(), FD,
- temp_file_path);
- if (err_code)
- return Status("Failed to create temp file: %s", err_code.message().c_str());
-
- llvm::FileRemover tmp_file_remover(temp_file_path);
-
- {
- llvm::raw_fd_ostream temp_file(FD, true);
- temp_file << socket_id;
- temp_file.close();
- if (temp_file.has_error())
- return Status("Failed to write to port file.");
- }
-
- err_code = llvm::sys::fs::rename(temp_file_path, file_spec.GetPath());
- if (err_code)
- return Status("Failed to rename file %s to %s: %s", temp_file_path.c_str(),
- file_spec.GetPath().c_str(), err_code.message().c_str());
- tmp_file_remover.releaseFile();
- return Status();
+ Status status;
+ if (auto Err =
+ handleErrors(llvm::writeFileAtomically(
+ temp_file_path, temp_file_spec.GetPath(), socket_id),
+ [&status, &temp_file_path,
+ &file_spec](const AtomicFileWriteError &E) {
+ std::string ErrorMsgBuffer;
+ llvm::raw_string_ostream S(ErrorMsgBuffer);
+ E.log(S);
+
+ switch (E.Error) {
+ case atomic_write_error::failed_to_create_uniq_file:
+ status = Status("Failed to create temp file: %s",
+ ErrorMsgBuffer.c_str());
+ case atomic_write_error::output_stream_error:
+ status = Status("Failed to write to port file.");
+ case atomic_write_error::failed_to_rename_temp_file:
+ status = Status("Failed to rename file %s to %s: %s",
+ ErrorMsgBuffer.c_str(),
+ file_spec.GetPath().c_str(),
+ ErrorMsgBuffer.c_str());
+ }
+ })) {
+ return Status("Failed to atomically write file %s",
+ file_spec.GetPath().c_str());
+ }
+ return status;
}
// main
diff --git a/llvm/include/llvm/Support/FileUtilities.h b/llvm/include/llvm/Support/FileUtilities.h
index 715ed80d537..04efdced32a 100644
--- a/llvm/include/llvm/Support/FileUtilities.h
+++ b/llvm/include/llvm/Support/FileUtilities.h
@@ -16,6 +16,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Errc.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
@@ -75,10 +76,40 @@ namespace llvm {
void releaseFile() { DeleteIt = false; }
};
+ enum class atomic_write_error {
+ failed_to_create_uniq_file = 0,
+ output_stream_error,
+ failed_to_rename_temp_file
+ };
+
+ class AtomicFileWriteError : public llvm::ErrorInfo<AtomicFileWriteError> {
+ public:
+ AtomicFileWriteError(atomic_write_error Error) : Error(Error) {}
+
+ void log(raw_ostream &OS) const override;
+
+ const atomic_write_error Error;
+ static char ID;
+
+ private:
+ // Users are not expected to use error_code.
+ std::error_code convertToErrorCode() const override {
+ return llvm::inconvertibleErrorCode();
+ }
+ };
+
+ // atomic_write_error + whatever the Writer can return
+
/// Creates a unique file with name according to the given \p TempPathModel,
/// writes content of \p Buffer to the file and renames it to \p FinalPath.
+ ///
+ /// \returns \c AtomicFileWriteError in case of error.
llvm::Error writeFileAtomically(StringRef TempPathModel, StringRef FinalPath,
StringRef Buffer);
+
+ llvm::Error
+ writeFileAtomically(StringRef TempPathModel, StringRef FinalPath,
+ std::function<llvm::Error(llvm::raw_ostream &)> Writer);
} // End llvm namespace
#endif
diff --git a/llvm/lib/LTO/ThinLTOCodeGenerator.cpp b/llvm/lib/LTO/ThinLTOCodeGenerator.cpp
index 02c0d41d132..db3ca90d905 100644
--- a/llvm/lib/LTO/ThinLTOCodeGenerator.cpp
+++ b/llvm/lib/LTO/ThinLTOCodeGenerator.cpp
@@ -39,6 +39,7 @@
#include "llvm/Support/CachePruning.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Error.h"
+#include "llvm/Support/FileUtilities.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/SHA1.h"
#include "llvm/Support/SmallVectorMemoryBuffer.h"
@@ -368,23 +369,26 @@ public:
// Write to a temporary to avoid race condition
SmallString<128> TempFilename;
SmallString<128> CachePath(EntryPath);
- int TempFD;
llvm::sys::path::remove_filename(CachePath);
sys::path::append(TempFilename, CachePath, "Thin-%%%%%%.tmp.o");
- std::error_code EC =
- sys::fs::createUniqueFile(TempFilename, TempFD, TempFilename);
- if (EC) {
- errs() << "Error: " << EC.message() << "\n";
- report_fatal_error("ThinLTO: Can't get a temporary file");
- }
- {
- raw_fd_ostream OS(TempFD, /* ShouldClose */ true);
- OS << OutputBuffer.getBuffer();
+
+ if (auto Err = handleErrors(
+ llvm::writeFileAtomically(TempFilename, EntryPath,
+ OutputBuffer.getBuffer()),
+ [](const llvm::AtomicFileWriteError &E) {
+ std::string ErrorMsgBuffer;
+ llvm::raw_string_ostream S(ErrorMsgBuffer);
+ E.log(S);
+
+ if (E.Error ==
+ llvm::atomic_write_error::failed_to_create_uniq_file) {
+ errs() << "Error: " << ErrorMsgBuffer << "\n";
+ report_fatal_error("ThinLTO: Can't get a temporary file");
+ }
+ })) {
+ // FIXME
+ consumeError(std::move(Err));
}
- // Rename temp file to final destination; rename is atomic
- EC = sys::fs::rename(TempFilename, EntryPath);
- if (EC)
- sys::fs::remove(TempFilename);
}
};
diff --git a/llvm/lib/Support/FileUtilities.cpp b/llvm/lib/Support/FileUtilities.cpp
index b933692d92e..d11fbb54dc0 100644
--- a/llvm/lib/Support/FileUtilities.cpp
+++ b/llvm/lib/Support/FileUtilities.cpp
@@ -12,7 +12,9 @@
//===----------------------------------------------------------------------===//
#include "llvm/Support/FileUtilities.h"
+#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
@@ -266,36 +268,65 @@ int llvm::DiffFilesWithTolerance(StringRef NameA,
return CompareFailed;
}
-Error llvm::writeFileAtomically(StringRef TempPathModel, StringRef FinalPath,
- StringRef Buffer) {
+void llvm::AtomicFileWriteError::log(raw_ostream &OS) const {
+ OS << "atomic_write_error: ";
+ switch (Error) {
+ case atomic_write_error::failed_to_create_uniq_file:
+ OS << "failed_to_create_uniq_file";
+ return;
+ case atomic_write_error::output_stream_error:
+ OS << "output_stream_error";
+ return;
+ case atomic_write_error::failed_to_rename_temp_file:
+ OS << "failed_to_rename_temp_file";
+ return;
+ }
+ llvm_unreachable("unknown atomic_write_error value in "
+ "failed_to_rename_temp_file::log()");
+}
+
+llvm::Error llvm::writeFileAtomically(StringRef TempPathModel,
+ StringRef FinalPath, StringRef Buffer) {
+ return writeFileAtomically(TempPathModel, FinalPath,
+ [&Buffer](llvm::raw_ostream &OS) {
+ OS.write(Buffer.data(), Buffer.size());
+ return llvm::Error::success();
+ });
+}
+
+llvm::Error llvm::writeFileAtomically(
+ StringRef TempPathModel, StringRef FinalPath,
+ std::function<llvm::Error(llvm::raw_ostream &)> Writer) {
SmallString<128> GeneratedUniqPath;
int TempFD;
- if (const std::error_code Error = sys::fs::createUniqueFile(
- TempPathModel.str(), TempFD, GeneratedUniqPath)) {
- return createStringError(
- Error, "failed to create temporary file with model \"%s\"",
- TempPathModel.str().c_str());
+ if (sys::fs::createUniqueFile(TempPathModel.str(), TempFD,
+ GeneratedUniqPath)) {
+ return llvm::make_error<AtomicFileWriteError>(
+ atomic_write_error::failed_to_create_uniq_file);
}
+ llvm::FileRemover RemoveTmpFileOnFail(GeneratedUniqPath);
raw_fd_ostream OS(TempFD, /*shouldClose=*/true);
- OS.write(Buffer.data(), Buffer.size());
- OS.close();
- TempFD = -1;
+ if (llvm::Error Err = Writer(OS)) {
+ return Err;
+ }
+ OS.close();
if (OS.has_error()) {
- const std::error_code Error = OS.error();
OS.clear_error();
- return createStringError(Error, "failed to write to \"%s\"",
- GeneratedUniqPath.c_str());
+ return llvm::make_error<AtomicFileWriteError>(
+ atomic_write_error::output_stream_error);
}
if (const std::error_code Error =
sys::fs::rename(/*from=*/GeneratedUniqPath.c_str(),
/*to=*/FinalPath.str().c_str())) {
- return createStringError(Error, "failed to rename file \"%s\" to \"%s\"",
- GeneratedUniqPath.c_str(),
- FinalPath.str().c_str());
+ return llvm::make_error<AtomicFileWriteError>(
+ atomic_write_error::failed_to_rename_temp_file);
}
+ RemoveTmpFileOnFail.releaseFile();
return Error::success();
}
+
+char llvm::AtomicFileWriteError::ID;
OpenPOWER on IntegriCloud