aboutsummaryrefslogtreecommitdiff
path: root/src/zencore/basicfile.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/zencore/basicfile.cpp')
-rw-r--r--src/zencore/basicfile.cpp79
1 files changed, 60 insertions, 19 deletions
diff --git a/src/zencore/basicfile.cpp b/src/zencore/basicfile.cpp
index b3bffd34d..6e879ca0d 100644
--- a/src/zencore/basicfile.cpp
+++ b/src/zencore/basicfile.cpp
@@ -281,6 +281,20 @@ BasicFile::StreamByteRange(uint64_t FileOffset, uint64_t Size, std::function<voi
}
uint64_t
+BasicFile::Write(const CompositeBuffer& Data, uint64_t FileOffset)
+{
+ std::error_code Ec;
+ uint64_t WrittenBytes = Write(Data, FileOffset, Ec);
+
+ if (Ec)
+ {
+ std::error_code Dummy;
+ throw std::system_error(Ec, fmt::format("Failed to write to file '{}'", zen::PathFromHandle(m_FileHandle, Dummy)));
+ }
+ return WrittenBytes;
+}
+
+uint64_t
BasicFile::Write(const CompositeBuffer& Data, uint64_t FileOffset, std::error_code& Ec)
{
uint64_t WrittenBytes = 0;
@@ -309,6 +323,8 @@ BasicFile::Write(MemoryView Data, uint64_t FileOffset, std::error_code& Ec)
void
BasicFile::Write(const void* Data, uint64_t Size, uint64_t FileOffset, std::error_code& Ec)
{
+ ZEN_ASSERT(m_FileHandle != nullptr);
+
Ec.clear();
const uint64_t MaxChunkSize = 2u * 1024 * 1024 * 1024;
@@ -817,6 +833,17 @@ BasicFileWriter::Write(const void* Data, uint64_t Size, uint64_t FileOffset)
}
void
+BasicFileWriter::Write(const CompositeBuffer& Data, uint64_t FileOffset)
+{
+ for (const SharedBuffer& Segment : Data.GetSegments())
+ {
+ const uint64_t SegmentSize = Segment.GetSize();
+ Write(Segment.GetData(), SegmentSize, FileOffset);
+ FileOffset += SegmentSize;
+ }
+}
+
+void
BasicFileWriter::Flush()
{
const uint64_t BufferedBytes = m_BufferEnd - m_BufferStart;
@@ -831,23 +858,20 @@ BasicFileWriter::Flush()
}
IoBuffer
-WriteToTempFile(CompositeBuffer&& Buffer, const std::filesystem::path& Path, std::function<bool(std::error_code& Ec)>&& RetryCallback)
+WriteToTempFile(const CompositeBuffer& Buffer, const std::filesystem::path& Path)
{
- if (std::filesystem::is_regular_file(Path))
+ TemporaryFile Temp;
+ std::error_code Ec;
+ Temp.CreateTemporary(Path.parent_path(), Ec);
+ if (Ec)
{
- IoBuffer ExistingTempFile = IoBuffer(IoBufferBuilder::MakeFromFile(Path));
- if (ExistingTempFile && ExistingTempFile.GetSize() == Buffer.GetSize())
- {
- ExistingTempFile.SetDeleteOnClose(true);
- return ExistingTempFile;
- }
+ throw std::system_error(Ec, fmt::format("Failed to create temp file for blob at '{}'", Path));
}
- BasicFile BlockFile;
- BlockFile.Open(Path, BasicFile::Mode::kTruncateDelete, std::move(RetryCallback));
- uint64_t Offset = 0;
+
{
+ uint64_t Offset = 0;
static const uint64_t BufferingSize = 256u * 1024u;
- BasicFileWriter BufferedOutput(BlockFile, BufferingSize / 2);
+ // BasicFileWriter BufferedOutput(BlockFile, BufferingSize / 2);
for (const SharedBuffer& Segment : Buffer.GetSegments())
{
size_t SegmentSize = Segment.GetSize();
@@ -859,22 +883,39 @@ WriteToTempFile(CompositeBuffer&& Buffer, const std::filesystem::path& Path, std
FileRef.FileChunkOffset,
FileRef.FileChunkSize,
BufferingSize,
- [&BufferedOutput, &Offset](const void* Data, size_t Size) {
- BufferedOutput.Write(Data, Size, Offset);
+ [&Temp, &Offset](const void* Data, size_t Size) {
+ Temp.Write(Data, Size, Offset);
Offset += Size;
});
}
else
{
- BufferedOutput.Write(Segment.GetData(), SegmentSize, Offset);
+ Temp.Write(Segment.GetData(), SegmentSize, Offset);
Offset += SegmentSize;
}
}
}
- void* FileHandle = BlockFile.Detach();
- IoBuffer BlockBuffer = IoBuffer(IoBuffer::File, FileHandle, 0, Offset, /*IsWholeFile*/ true);
- BlockBuffer.SetDeleteOnClose(true);
- return BlockBuffer;
+
+ Temp.MoveTemporaryIntoPlace(Path, Ec);
+ if (Ec)
+ {
+ IoBuffer TmpBuffer = IoBufferBuilder::MakeFromFile(Path);
+ if (TmpBuffer)
+ {
+ IoHash ExistingHash = IoHash::HashBuffer(TmpBuffer);
+ const IoHash ExpectedHash = IoHash::HashBuffer(Buffer);
+ if (ExistingHash == ExpectedHash)
+ {
+ TmpBuffer.SetDeleteOnClose(true);
+ return TmpBuffer;
+ }
+ }
+ throw std::system_error(Ec, fmt::format("Failed to move temp file to '{}'", Path));
+ }
+
+ IoBuffer TmpBuffer = IoBufferBuilder::MakeFromFile(Path);
+ TmpBuffer.SetDeleteOnClose(true);
+ return TmpBuffer;
}
//////////////////////////////////////////////////////////////////////////