aboutsummaryrefslogtreecommitdiff
path: root/zenstore/basicfile.cpp
diff options
context:
space:
mode:
authorDan Engelbrecht <[email protected]>2022-03-24 22:41:46 +0100
committerDan Engelbrecht <[email protected]>2022-03-31 11:29:27 +0200
commit52bf08afc4b9da9ccdd73089c8ebfc7bda859bd3 (patch)
tree87fdb172c98fd05b5c64398cce6b1c6be6db257e /zenstore/basicfile.cpp
parentclean up paths (diff)
downloadzen-52bf08afc4b9da9ccdd73089c8ebfc7bda859bd3.tar.xz
zen-52bf08afc4b9da9ccdd73089c8ebfc7bda859bd3.zip
Migration now works in larger disk IO chunks
BasicFile and CasLogFile now has new explicit modes instead of create true/false
Diffstat (limited to 'zenstore/basicfile.cpp')
-rw-r--r--zenstore/basicfile.cpp64
1 files changed, 40 insertions, 24 deletions
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<uint32_t>(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<uint32_t>(kAccessTruncate)) ? CREATE_ALWAYS : OPEN_EXISTING;
+ DWORD dwDesiredAccess = GENERIC_READ;
+ dwDesiredAccess |= (ModeFlags & static_cast<uint32_t>(kAccessWrite)) ? GENERIC_WRITE : 0;
+ dwDesiredAccess |= (ModeFlags & static_cast<uint32_t>(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<uint32_t>(kAccessWrite)) ? O_RDWR : 0;
+ OpenFlags |= (ModeFlags & static_cast<uint32_t>(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<uint64_t>(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<uint8_t*>(Data) + NumberOfBytesToRead;
+ BytesToRead -= NumberOfBytesRead;
+ FileOffset += NumberOfBytesRead;
+ Data = reinterpret_cast<uint8_t*>(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);
{