[+] IIOHandle::SectionLock
[+] IIOHandle::SectionUnlock [*] FileSteam.NT.cpp clean up
This commit is contained in:
parent
c3165de4cf
commit
828430889c
@ -133,6 +133,13 @@ namespace Aurora::IO
|
||||
virtual bool IsTTY() = 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);
|
||||
|
@ -7,6 +7,7 @@
|
||||
***/
|
||||
#include <RuntimeInternal.hpp>
|
||||
#include "AuIOHandle.hpp"
|
||||
#include "FS/FileAdvisory.hpp"
|
||||
|
||||
namespace Aurora::IO
|
||||
{
|
||||
@ -272,4 +273,17 @@ namespace Aurora::IO
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
@ -59,6 +59,13 @@ namespace Aurora::IO
|
||||
void InitStdIn(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> uOSReadHandle;
|
||||
AuSPtr<IIOHandle> pThat;
|
||||
|
@ -7,6 +7,7 @@
|
||||
***/
|
||||
#include <Source/RuntimeInternal.hpp>
|
||||
#include "FS.hpp"
|
||||
#include "FileAdvisory.hpp"
|
||||
#include "FileAdvisory.NT.hpp"
|
||||
|
||||
namespace Aurora::IO::FS
|
||||
@ -25,4 +26,170 @@ namespace Aurora::IO::FS
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
@ -7,6 +7,7 @@
|
||||
***/
|
||||
#include <Source/RuntimeInternal.hpp>
|
||||
#include "FS.hpp"
|
||||
#include "FileAdvisory.hpp"
|
||||
#include "FileAdvisory.Unix.hpp"
|
||||
#include <sys/file.h>
|
||||
|
||||
@ -55,7 +56,7 @@ namespace Aurora::IO::FS
|
||||
lease = F_RDLCK;
|
||||
break;
|
||||
case EFileAdvisoryLockLevel::eBlockReadWrite:
|
||||
lease = F_RDLCK;
|
||||
lease = F_WRLCK;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -92,4 +93,86 @@ namespace Aurora::IO::FS
|
||||
return ::fcntl(fd, F_OFD_SETLK, &lck) == 0;
|
||||
#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
|
||||
}
|
||||
}
|
20
Source/IO/FS/FileAdvisory.hpp
Normal file
20
Source/IO/FS/FileAdvisory.hpp
Normal 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);
|
||||
}
|
@ -143,6 +143,9 @@ namespace Aurora::IO::FS
|
||||
|
||||
bool WinFileStream::Read(const Memory::MemoryViewStreamWrite ¶meters)
|
||||
{
|
||||
OVERLAPPED overlapped {};
|
||||
AuUInt64 uOffset {};
|
||||
|
||||
if (!this->pHandle_)
|
||||
{
|
||||
SysPushErrorUninitialized();
|
||||
@ -159,16 +162,19 @@ namespace Aurora::IO::FS
|
||||
}
|
||||
|
||||
bool bIsAsync = this->pHandle_->IsAsync();
|
||||
|
||||
if (bIsAsync)
|
||||
{
|
||||
hEventHandle = ::CreateEventA(nullptr, false, false, nullptr);
|
||||
if (!hEventHandle)
|
||||
{
|
||||
SysPushErrorGeneric();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
parameters.outVariable = 0;
|
||||
|
||||
AuUInt64 uLength = parameters.length;
|
||||
AuUInt64 uOffset {};
|
||||
while (uLength)
|
||||
{
|
||||
DWORD read {};
|
||||
@ -177,24 +183,27 @@ namespace Aurora::IO::FS
|
||||
|
||||
if (this->pHandle_->IsAsync())
|
||||
{
|
||||
OVERLAPPED overlapped {};
|
||||
overlapped.hEvent = hEventHandle;
|
||||
|
||||
if (!::ReadFile(hHandle,
|
||||
reinterpret_cast<char *>(parameters.ptr) + uOffset,
|
||||
blockSize,
|
||||
NULL,
|
||||
&overlapped) &&
|
||||
::GetLastError() != ERROR_IO_PENDING)
|
||||
&overlapped))
|
||||
{
|
||||
SysPushErrorIO("ReadFile IO Error: 0x{:x}, {}", GetLastError(), this->pHandle_ ? this->pHandle_->GetPath() : "");
|
||||
AuWin32CloseHandle(hEventHandle);
|
||||
parameters.outVariable = uOffset;
|
||||
return false;
|
||||
if (::GetLastError() == ERROR_IO_PENDING)
|
||||
{
|
||||
::WaitForSingleObject(hEventHandle, 0);
|
||||
}
|
||||
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 (::GetLastError() != ERROR_HANDLE_EOF)
|
||||
@ -236,6 +245,9 @@ namespace Aurora::IO::FS
|
||||
|
||||
bool WinFileStream::Write(const Memory::MemoryViewStreamRead ¶meters)
|
||||
{
|
||||
OVERLAPPED overlapped {};
|
||||
AuUInt64 uOffset {};
|
||||
|
||||
auto optHandle = this->GetHandle()->GetOSWriteHandleSafe();
|
||||
if (!optHandle)
|
||||
{
|
||||
@ -257,11 +269,15 @@ namespace Aurora::IO::FS
|
||||
if (bIsAsync)
|
||||
{
|
||||
hEventHandle = ::CreateEventA(nullptr, false, false, nullptr);
|
||||
if (!hEventHandle)
|
||||
{
|
||||
SysPushErrorGeneric();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
parameters.outVariable = 0;
|
||||
|
||||
AuUInt64 uLength = parameters.length;
|
||||
AuUInt64 uOffset {};
|
||||
while (uLength)
|
||||
{
|
||||
DWORD written {};
|
||||
@ -270,24 +286,27 @@ namespace Aurora::IO::FS
|
||||
|
||||
if (bIsAsync)
|
||||
{
|
||||
OVERLAPPED overlapped {};
|
||||
overlapped.hEvent = hEventHandle;
|
||||
|
||||
if (!::WriteFile(hHandle,
|
||||
reinterpret_cast<const char *>(parameters.ptr) + uOffset,
|
||||
uBlockSize,
|
||||
NULL,
|
||||
&overlapped) &&
|
||||
::GetLastError() != ERROR_IO_PENDING)
|
||||
&overlapped))
|
||||
{
|
||||
SysPushErrorIO("WriteFile IO Error: 0x{:x}, {}", GetLastError(), this->pHandle_ ? this->pHandle_->GetPath() : "");
|
||||
AuWin32CloseHandle(hEventHandle);
|
||||
parameters.outVariable = uOffset;
|
||||
return false;
|
||||
if (GetLastError() == ERROR_IO_PENDING)
|
||||
{
|
||||
::WaitForSingleObject(hEventHandle, 0);
|
||||
}
|
||||
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))
|
||||
{
|
||||
AuWin32CloseHandle(hEventHandle);
|
||||
|
Loading…
Reference in New Issue
Block a user