From 52bf08afc4b9da9ccdd73089c8ebfc7bda859bd3 Mon Sep 17 00:00:00 2001 From: Dan Engelbrecht Date: Thu, 24 Mar 2022 22:41:46 +0100 Subject: Migration now works in larger disk IO chunks BasicFile and CasLogFile now has new explicit modes instead of create true/false --- zenstore/basicfile.cpp | 64 +++++++++++++++++++++++++++++++------------------- 1 file changed, 40 insertions(+), 24 deletions(-) (limited to 'zenstore/basicfile.cpp') diff --git a/zenstore/basicfile.cpp b/zenstore/basicfile.cpp index 77bada95f..fc7282941 100644 --- a/zenstore/basicfile.cpp +++ b/zenstore/basicfile.cpp @@ -29,10 +29,10 @@ BasicFile::~BasicFile() } void -BasicFile::Open(const std::filesystem::path& FileName, bool IsCreate) +BasicFile::Open(const std::filesystem::path& FileName, EMode Mode) { std::error_code Ec; - Open(FileName, IsCreate, Ec); + Open(FileName, Mode, Ec); if (Ec) { @@ -41,16 +41,20 @@ BasicFile::Open(const std::filesystem::path& FileName, bool IsCreate) } void -BasicFile::Open(const std::filesystem::path& FileName, bool IsCreate, std::error_code& Ec) +BasicFile::Open(const std::filesystem::path& FileName, EMode Mode, std::error_code& Ec) { Ec.clear(); + uint32_t ModeFlags = static_cast(Mode); #if ZEN_PLATFORM_WINDOWS - const DWORD dwCreationDisposition = IsCreate ? CREATE_ALWAYS : OPEN_EXISTING; - DWORD dwDesiredAccess = GENERIC_READ | GENERIC_WRITE | DELETE; - const DWORD dwShareMode = FILE_SHARE_READ; - const DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL; - HANDLE hTemplateFile = nullptr; + const DWORD dwCreationDisposition = (ModeFlags & static_cast(kAccessTruncate)) ? CREATE_ALWAYS : OPEN_EXISTING; + DWORD dwDesiredAccess = GENERIC_READ; + dwDesiredAccess |= (ModeFlags & static_cast(kAccessWrite)) ? GENERIC_WRITE : 0; + dwDesiredAccess |= (ModeFlags & static_cast(kAccessDelete)) ? DELETE : 0; + + const DWORD dwShareMode = FILE_SHARE_READ; + const DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL; + HANDLE hTemplateFile = nullptr; HANDLE FileHandle = CreateFile(FileName.c_str(), dwDesiredAccess, @@ -67,8 +71,9 @@ BasicFile::Open(const std::filesystem::path& FileName, bool IsCreate, std::error return; } #else - int OpenFlags = O_RDWR | O_CLOEXEC; - OpenFlags |= IsCreate ? O_CREAT | O_TRUNC : 0; + int OpenFlags = O_CLOEXEC; + OpenFlags |= (ModeFlags & static_cast(kAccessWrite)) ? O_RDWR : 0; + OpenFlags |= (ModeFlags & static_cast(kAccessTruncate)) ? (O_CREAT | O_TRUNC) : 0; int Fd = open(FileName.c_str(), OpenFlags, 0666); if (Fd < 0) @@ -105,27 +110,33 @@ BasicFile::Close() void BasicFile::Read(void* Data, uint64_t BytesToRead, uint64_t FileOffset) { - const uint64_t MaxChunkSize = 2u * 1024 * 1024 * 1024; + const uint64_t MaxChunkSize = 2u * 1024 * 1024 * 1024; + uint64_t TotalFileSize = FileSize(); + ZEN_ASSERT((FileOffset + BytesToRead) <= TotalFileSize); while (BytesToRead) { const uint64_t NumberOfBytesToRead = Min(BytesToRead, MaxChunkSize); + uint64_t NumberOfBytesRead; #if ZEN_PLATFORM_WINDOWS OVERLAPPED Ovl{}; Ovl.Offset = DWORD(FileOffset & 0xffff'ffffu); Ovl.OffsetHigh = DWORD(FileOffset >> 32); + ZEN_ASSERT((FileOffset + NumberOfBytesToRead) <= TotalFileSize); DWORD dwNumberOfBytesRead = 0; BOOL Success = ::ReadFile(m_FileHandle, Data, DWORD(NumberOfBytesToRead), &dwNumberOfBytesRead, &Ovl); - ZEN_ASSERT(dwNumberOfBytesRead == NumberOfBytesToRead); + ZEN_ASSERT((dwNumberOfBytesRead <= NumberOfBytesToRead) && (dwNumberOfBytesRead > 0)); + NumberOfBytesRead = dwNumberOfBytesRead; #else static_assert(sizeof(off_t) >= sizeof(uint64_t), "sizeof(off_t) does not support large files"); - int Fd = int(uintptr_t(m_FileHandle)); - int BytesRead = pread(Fd, Data, NumberOfBytesToRead, FileOffset); - bool Success = (BytesRead > 0); + int Fd = int(uintptr_t(m_FileHandle)); + int BytesRead = pread(Fd, Data, NumberOfBytesToRead, FileOffset); + bool Success = (BytesRead > 0); + NumberOfBytesRead = static_cast(BytesRead); #endif if (!Success) @@ -133,9 +144,9 @@ BasicFile::Read(void* Data, uint64_t BytesToRead, uint64_t FileOffset) ThrowLastError(fmt::format("Failed to read from file '{}'", zen::PathFromHandle(m_FileHandle))); } - BytesToRead -= NumberOfBytesToRead; - FileOffset += NumberOfBytesToRead; - Data = reinterpret_cast(Data) + NumberOfBytesToRead; + BytesToRead -= NumberOfBytesRead; + FileOffset += NumberOfBytesRead; + Data = reinterpret_cast(Data) + NumberOfBytesRead; } } @@ -263,7 +274,14 @@ BasicFile::FileSize() #if ZEN_PLATFORM_WINDOWS ULARGE_INTEGER liFileSize; liFileSize.LowPart = ::GetFileSize(m_FileHandle, &liFileSize.HighPart); - + if (liFileSize.LowPart == INVALID_FILE_SIZE) + { + int Error = GetLastError(); + if (Error) + { + ThrowSystemError(Error, fmt::format("Failed to get file size from file '{}'", zen::PathFromHandle(m_FileHandle))); + } + } return uint64_t(liFileSize.QuadPart); #else int Fd = int(uintptr_t(m_FileHandle)); @@ -351,9 +369,7 @@ TemporaryFile::CreateTemporary(std::filesystem::path TempDirName, std::error_cod m_TempPath = TempDirName / TempName.c_str(); - const bool IsCreate = true; - - Open(m_TempPath, IsCreate, Ec); + Open(m_TempPath, BasicFile::EMode::kTruncateDelete, Ec); } void @@ -453,8 +469,8 @@ TEST_CASE("BasicFile") ScopedCurrentDirectoryChange _; BasicFile File1; - CHECK_THROWS(File1.Open("zonk", false)); - CHECK_NOTHROW(File1.Open("zonk", true)); + CHECK_THROWS(File1.Open("zonk", BasicFile::EMode::kRead)); + CHECK_NOTHROW(File1.Open("zonk", BasicFile::EMode::kTruncate)); CHECK_NOTHROW(File1.Write("abcd", 4, 0)); CHECK(File1.FileSize() == 4); { -- cgit v1.2.3