[+] IIOHandle::SectionLock

[+] IIOHandle::SectionUnlock
[*] FileSteam.NT.cpp clean up
This commit is contained in:
Reece Wilson 2023-09-23 04:38:26 +01:00
parent c3165de4cf
commit 828430889c
7 changed files with 339 additions and 22 deletions

View File

@ -133,6 +133,13 @@ namespace Aurora::IO
virtual bool IsTTY() = 0; virtual bool IsTTY() = 0;
virtual bool IsPipe() = 0; virtual bool IsPipe() = 0;
virtual bool SectionLock(AuUInt64 uOffset,
AuUInt64 uLength,
FS::EFileAdvisoryLockLevel level) = 0;
virtual bool SectionUnlock(AuUInt64 uOffset,
AuUInt64 uLength) = 0;
}; };
AUKN_SHARED_SOO_NC(IOHandle, IIOHandle, 256); AUKN_SHARED_SOO_NC(IOHandle, IIOHandle, 256);

View File

@ -7,6 +7,7 @@
***/ ***/
#include <RuntimeInternal.hpp> #include <RuntimeInternal.hpp>
#include "AuIOHandle.hpp" #include "AuIOHandle.hpp"
#include "FS/FileAdvisory.hpp"
namespace Aurora::IO namespace Aurora::IO
{ {
@ -272,4 +273,17 @@ namespace Aurora::IO
{ {
return this->path; return this->path;
} }
bool AFileHandle::SectionLock(AuUInt64 uOffset,
AuUInt64 uLength,
FS::EFileAdvisoryLockLevel level)
{
return FS::ApplyFileSectionLock(AuUnsafeRaiiToShared(this), level, uOffset, uLength);
}
bool AFileHandle::SectionUnlock(AuUInt64 uOffset,
AuUInt64 uLength)
{
return FS::UnapplyFileSectionLock(AuUnsafeRaiiToShared(this), uOffset, uLength);
}
} }

View File

@ -59,6 +59,13 @@ namespace Aurora::IO
void InitStdIn(bool bSharing = false); void InitStdIn(bool bSharing = false);
void InitStdOut(bool bError = false, bool bSharing = false); void InitStdOut(bool bError = false, bool bSharing = false);
bool SectionLock(AuUInt64 uOffset,
AuUInt64 uLength,
FS::EFileAdvisoryLockLevel level) override;
bool SectionUnlock(AuUInt64 uOffset,
AuUInt64 uLength) override;
AuOptionalEx<AuUInt64> uOSWriteHandle; AuOptionalEx<AuUInt64> uOSWriteHandle;
AuOptionalEx<AuUInt64> uOSReadHandle; AuOptionalEx<AuUInt64> uOSReadHandle;
AuSPtr<IIOHandle> pThat; AuSPtr<IIOHandle> pThat;

View File

@ -7,6 +7,7 @@
***/ ***/
#include <Source/RuntimeInternal.hpp> #include <Source/RuntimeInternal.hpp>
#include "FS.hpp" #include "FS.hpp"
#include "FileAdvisory.hpp"
#include "FileAdvisory.NT.hpp" #include "FileAdvisory.NT.hpp"
namespace Aurora::IO::FS namespace Aurora::IO::FS
@ -25,4 +26,170 @@ namespace Aurora::IO::FS
} }
return 0; return 0;
} }
bool ApplyFileSectionLock(AuSPtr<IIOHandle> pHandle,
EFileAdvisoryLockLevel level,
AuUInt64 uOffset,
AuUInt64 uLength)
{
DWORD dwFlags {};
OVERLAPPED overlapped {};
HANDLE hEventHandle { INVALID_HANDLE_VALUE };
if (!pHandle)
{
SysPushErrorUninitialized();
return false;
}
if (!pHandle->IsFile())
{
SysPushErrorIOResourceRejected();
return false;
}
switch (level)
{
case EFileAdvisoryLockLevel::eEnumCount:
case EFileAdvisoryLockLevel::eNoSafety:
return true;
case EFileAdvisoryLockLevel::eBlockWrite:
break;
case EFileAdvisoryLockLevel::eBlockReadWrite:
dwFlags |= LOCKFILE_EXCLUSIVE_LOCK;
break;
}
auto hHandle = (HANDLE)pHandle->GetOSHandleSafe().ValueOr((AuUInt)INVALID_HANDLE_VALUE);
if (hHandle == INVALID_HANDLE_VALUE)
{
SysPushErrorIOResourceRejected();
return false;
}
bool bIsAsync = pHandle->IsAsync();
if (bIsAsync)
{
hEventHandle = ::CreateEventA(nullptr, false, false, nullptr);
if (!hEventHandle)
{
SysPushErrorGeneric();
return false;
}
overlapped.hEvent = hEventHandle;
}
overlapped.Offset = AuBitsToLower(uOffset);
overlapped.OffsetHigh = AuBitsToHigher(uOffset);
dwFlags |= LOCKFILE_FAIL_IMMEDIATELY;
if (!LockFileEx(hHandle,
dwFlags,
0,
AuBitsToLower(uLength),
AuBitsToHigher(uLength),
&overlapped))
{
if (GetLastError() == ERROR_IO_PENDING)
{
::WaitForSingleObject(hEventHandle, 0);
DWORD idc {};
if (!::GetOverlappedResult(hHandle,
&overlapped,
&idc,
true))
{
AuWin32CloseHandle(hEventHandle);
return false;
}
}
else
{
AuWin32CloseHandle(hEventHandle);
return false;
}
}
AuWin32CloseHandle(hEventHandle);
return true;
}
bool UnapplyFileSectionLock(AuSPtr<IIOHandle> pHandle,
AuUInt64 uOffset,
AuUInt64 uLength)
{
DWORD dwFlags {};
OVERLAPPED overlapped {};
HANDLE hEventHandle { INVALID_HANDLE_VALUE };
if (!pHandle)
{
SysPushErrorUninitialized();
return false;
}
if (!pHandle->IsFile())
{
SysPushErrorIOResourceRejected();
return false;
}
auto hHandle = (HANDLE)pHandle->GetOSHandleSafe().ValueOr((AuUInt)INVALID_HANDLE_VALUE);
if (hHandle == INVALID_HANDLE_VALUE)
{
SysPushErrorIOResourceRejected();
return false;
}
bool bIsAsync = pHandle->IsAsync();
if (bIsAsync)
{
hEventHandle = ::CreateEventA(nullptr, false, false, nullptr);
if (!hEventHandle)
{
SysPushErrorGeneric();
return false;
}
overlapped.hEvent = hEventHandle;
}
dwFlags |= LOCKFILE_FAIL_IMMEDIATELY;
overlapped.Offset = AuBitsToLower(uOffset);
overlapped.OffsetHigh = AuBitsToHigher(uOffset);
if (!UnlockFileEx(hHandle,
0,
AuBitsToLower(uLength),
AuBitsToHigher(uLength),
&overlapped))
{
if (GetLastError() == ERROR_IO_PENDING)
{
::WaitForSingleObject(hEventHandle, 0);
DWORD idc {};
if (!::GetOverlappedResult(hHandle,
&overlapped,
&idc,
true))
{
AuWin32CloseHandle(hEventHandle);
return false;
}
}
else
{
AuWin32CloseHandle(hEventHandle);
return false;
}
}
AuWin32CloseHandle(hEventHandle);
return true;
}
} }

View File

@ -7,6 +7,7 @@
***/ ***/
#include <Source/RuntimeInternal.hpp> #include <Source/RuntimeInternal.hpp>
#include "FS.hpp" #include "FS.hpp"
#include "FileAdvisory.hpp"
#include "FileAdvisory.Unix.hpp" #include "FileAdvisory.Unix.hpp"
#include <sys/file.h> #include <sys/file.h>
@ -55,7 +56,7 @@ namespace Aurora::IO::FS
lease = F_RDLCK; lease = F_RDLCK;
break; break;
case EFileAdvisoryLockLevel::eBlockReadWrite: case EFileAdvisoryLockLevel::eBlockReadWrite:
lease = F_RDLCK; lease = F_WRLCK;
break; break;
} }
@ -92,4 +93,86 @@ namespace Aurora::IO::FS
return ::fcntl(fd, F_OFD_SETLK, &lck) == 0; return ::fcntl(fd, F_OFD_SETLK, &lck) == 0;
#endif #endif
} }
bool ApplyFileSectionLock(AuSPtr<IIOHandle> pHandle,
EFileAdvisoryLockLevel level,
AuUInt64 uOffset,
AuUInt64 uLength)
{
int lease {};
auto opt = pHandle->GetOSHandleSafe();
if (!opt)
{
SysPushErrorIOResourceRejected();
return false;
}
int fd = (int)opt.ValueOr((int)-1);
if (opt == -1)
{
SysPushErrorIOResourceRejected();
return false;
}
switch (level)
{
case EFileAdvisoryLockLevel::eEnumCount:
case EFileAdvisoryLockLevel::eNoSafety:
return true;
case EFileAdvisoryLockLevel::eBlockWrite:
lease = F_RDLCK;
break;
case EFileAdvisoryLockLevel::eBlockReadWrite:
lease = F_WRLCK;
break;
}
struct flock lck =
{
.l_whence = SEEK_SET,
.l_start = uLength,
.l_len = uOffset,
.l_type = lease
};
#if defined(AURORA_IS_LINUX_DERIVED)
return ::fcntl(fd, F_OFD_SETLK, &lck) == 0;
#else
return ::fcntl(fd, F_SETLK, &lck) == 0;
#endif
}
bool UnapplyFileSectionLock(AuSPtr<IIOHandle> pHandle,
AuUInt64 uOffset,
AuUInt64 uLength)
{
auto opt = pHandle->GetOSHandleSafe();
if (!opt)
{
SysPushErrorIOResourceRejected();
return false;
}
int fd = (int)opt.ValueOr((int)-1);
if (opt == -1)
{
SysPushErrorIOResourceRejected();
return false;
}
struct flock lck =
{
.l_whence = SEEK_SET,
.l_start = uLength,
.l_len = uOffset,
.l_type = F_UNLCK
};
#if defined(AURORA_IS_LINUX_DERIVED)
return ::fcntl(fd, F_OFD_SETLK, &lck) == 0;
#else
return ::fcntl(fd, F_SETLK, &lck) == 0;
#endif
}
} }

View File

@ -0,0 +1,20 @@
/***
Copyright (C) 2023 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: FileAdvisory.hpp
Date: 2023-09-23
Author: Reece
***/
#pragma once
namespace Aurora::IO::FS
{
bool ApplyFileSectionLock(AuSPtr<IIOHandle> pHandle,
EFileAdvisoryLockLevel level,
AuUInt64 uOffset,
AuUInt64 uLength);
bool UnapplyFileSectionLock(AuSPtr<IIOHandle> pHandle,
AuUInt64 uOffset,
AuUInt64 uLength);
}

View File

@ -143,6 +143,9 @@ namespace Aurora::IO::FS
bool WinFileStream::Read(const Memory::MemoryViewStreamWrite &parameters) bool WinFileStream::Read(const Memory::MemoryViewStreamWrite &parameters)
{ {
OVERLAPPED overlapped {};
AuUInt64 uOffset {};
if (!this->pHandle_) if (!this->pHandle_)
{ {
SysPushErrorUninitialized(); SysPushErrorUninitialized();
@ -159,16 +162,19 @@ namespace Aurora::IO::FS
} }
bool bIsAsync = this->pHandle_->IsAsync(); bool bIsAsync = this->pHandle_->IsAsync();
if (bIsAsync) if (bIsAsync)
{ {
hEventHandle = ::CreateEventA(nullptr, false, false, nullptr); hEventHandle = ::CreateEventA(nullptr, false, false, nullptr);
if (!hEventHandle)
{
SysPushErrorGeneric();
return false;
}
} }
parameters.outVariable = 0; parameters.outVariable = 0;
AuUInt64 uLength = parameters.length; AuUInt64 uLength = parameters.length;
AuUInt64 uOffset {};
while (uLength) while (uLength)
{ {
DWORD read {}; DWORD read {};
@ -177,24 +183,27 @@ namespace Aurora::IO::FS
if (this->pHandle_->IsAsync()) if (this->pHandle_->IsAsync())
{ {
OVERLAPPED overlapped {};
overlapped.hEvent = hEventHandle; overlapped.hEvent = hEventHandle;
if (!::ReadFile(hHandle, if (!::ReadFile(hHandle,
reinterpret_cast<char *>(parameters.ptr) + uOffset, reinterpret_cast<char *>(parameters.ptr) + uOffset,
blockSize, blockSize,
NULL, NULL,
&overlapped) && &overlapped))
::GetLastError() != ERROR_IO_PENDING)
{ {
SysPushErrorIO("ReadFile IO Error: 0x{:x}, {}", GetLastError(), this->pHandle_ ? this->pHandle_->GetPath() : ""); if (::GetLastError() == ERROR_IO_PENDING)
AuWin32CloseHandle(hEventHandle); {
parameters.outVariable = uOffset; ::WaitForSingleObject(hEventHandle, 0);
return false; }
else
{
SysPushErrorIO("ReadFile IO Error: 0x{:x}, {}", GetLastError(), this->pHandle_ ? this->pHandle_->GetPath() : "");
AuWin32CloseHandle(hEventHandle);
parameters.outVariable = uOffset;
return false;
}
} }
::WaitForSingleObject(hEventHandle, 0);
if (!::GetOverlappedResult(hHandle, &overlapped, &read, true)) if (!::GetOverlappedResult(hHandle, &overlapped, &read, true))
{ {
if (::GetLastError() != ERROR_HANDLE_EOF) if (::GetLastError() != ERROR_HANDLE_EOF)
@ -236,6 +245,9 @@ namespace Aurora::IO::FS
bool WinFileStream::Write(const Memory::MemoryViewStreamRead &parameters) bool WinFileStream::Write(const Memory::MemoryViewStreamRead &parameters)
{ {
OVERLAPPED overlapped {};
AuUInt64 uOffset {};
auto optHandle = this->GetHandle()->GetOSWriteHandleSafe(); auto optHandle = this->GetHandle()->GetOSWriteHandleSafe();
if (!optHandle) if (!optHandle)
{ {
@ -257,11 +269,15 @@ namespace Aurora::IO::FS
if (bIsAsync) if (bIsAsync)
{ {
hEventHandle = ::CreateEventA(nullptr, false, false, nullptr); hEventHandle = ::CreateEventA(nullptr, false, false, nullptr);
if (!hEventHandle)
{
SysPushErrorGeneric();
return false;
}
} }
parameters.outVariable = 0; parameters.outVariable = 0;
AuUInt64 uLength = parameters.length; AuUInt64 uLength = parameters.length;
AuUInt64 uOffset {};
while (uLength) while (uLength)
{ {
DWORD written {}; DWORD written {};
@ -270,24 +286,27 @@ namespace Aurora::IO::FS
if (bIsAsync) if (bIsAsync)
{ {
OVERLAPPED overlapped {};
overlapped.hEvent = hEventHandle; overlapped.hEvent = hEventHandle;
if (!::WriteFile(hHandle, if (!::WriteFile(hHandle,
reinterpret_cast<const char *>(parameters.ptr) + uOffset, reinterpret_cast<const char *>(parameters.ptr) + uOffset,
uBlockSize, uBlockSize,
NULL, NULL,
&overlapped) && &overlapped))
::GetLastError() != ERROR_IO_PENDING)
{ {
SysPushErrorIO("WriteFile IO Error: 0x{:x}, {}", GetLastError(), this->pHandle_ ? this->pHandle_->GetPath() : ""); if (GetLastError() == ERROR_IO_PENDING)
AuWin32CloseHandle(hEventHandle); {
parameters.outVariable = uOffset; ::WaitForSingleObject(hEventHandle, 0);
return false; }
else
{
SysPushErrorIO("WriteFile IO Error: 0x{:x}, {}", GetLastError(), this->pHandle_ ? this->pHandle_->GetPath() : "");
AuWin32CloseHandle(hEventHandle);
parameters.outVariable = uOffset;
return false;
}
} }
::WaitForSingleObject(hEventHandle, 0);
if (!::GetOverlappedResult(hHandle, &overlapped, &written, true)) if (!::GetOverlappedResult(hHandle, &overlapped, &written, true))
{ {
AuWin32CloseHandle(hEventHandle); AuWin32CloseHandle(hEventHandle);