[+] AuIO::IIOHandle

This commit is contained in:
Reece Wilson 2023-07-29 08:02:47 +01:00
parent 0cf38d5fcd
commit 7e2aa2de3d
21 changed files with 988 additions and 334 deletions

View File

@ -15,4 +15,10 @@ namespace Aurora::IO::FS
bool bDirectIO = true, // true disables buffering under Win32
// true enables non-blocking ticks under Linux aio by bypassing the kernels cache
EFileAdvisoryLockLevel lock = EFileAdvisoryLockLevel::eNoSafety);
#if defined(AUX_FSAOPEX)
AUKN_SYM AuSPtr<IAsyncTransaction> OpenDirectIOAsyncFileStreamFromHandle(AuSPtr<IIOHandle> pIOHandle);
AUKN_SYM AuSPtr<IAsyncTransaction> OpenBufferedAsyncFileStreamFromHandle(AuSPtr<IIOHandle> pIOHandle);
#endif
}

View File

@ -18,4 +18,6 @@ namespace Aurora::IO::FS
AUKN_SHARED_API(OpenWrite, IFileStream, const AuString &path, EFileAdvisoryLockLevel successPostAdvisoryLevel = EFileAdvisoryLockLevel::eBlockReadWrite);
AUKN_SHARED_API(Open, IFileStream, const AuString &path, EFileOpenMode mode = EFileOpenMode::eRead, EFileAdvisoryLockLevel successPostAdvisoryLevel = EFileAdvisoryLockLevel::eBlockReadWrite);
AUKN_SYM AuSPtr<IFileStream> OpenBlockingFileStreamFromHandle(AuSPtr<IIOHandle> pIOHandle);
}

View File

@ -20,6 +20,8 @@
#include "Async.hpp"
#include "IOSleep.hpp"
#include "IOHandle.hpp"
#include "FS/FS.hpp"
#include "Net/Net.hpp"
#include "Character/Character.hpp"

View File

@ -0,0 +1,129 @@
/***
Copyright (C) 2023 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: IOHandle.hpp
Date: 2023-7-28
Author: Reece
***/
#pragma once
#include "FS/EFileAdvisoryLockLevel.hpp"
#include "FS/EFileOpenMode.hpp"
namespace Aurora::IO
{
// Note: A handle is never disposable to prevent IO fd use after close
// You must ensure RAII and/or shared ownership release to dispose of the IO handle.
// This class is only intended to be an handle view; therefore, it is not possible to close the handle.
struct IIOHandle
{
struct HandleCreate
{
/**
* "Create"
*/
bool bFailIfNonEmptyFile {};
/**
* Lock level
*/
FS::EFileAdvisoryLockLevel eAdvisoryLevel;
/**
* Path
*/
const AuString &path;
/**
* Mode
*/
FS::EFileOpenMode eMode;
/**
*
*/
bool bAlwaysCreateDirTree { true };
/**
* Indicates the handle will be for use with IAsyncTransactions as opposed to IFileStream and AuProcess
*/
bool bAsyncHandle { false };
/**
* Indicates the handle will only ever directly interface with the disk hardware as opposed to leveraging kernel assigned user shared memory
*/
bool bDirectIOMode { false };
cstatic HandleCreate Create(const AuString &path)
{
HandleCreate create(path);
create.bFailIfNonEmptyFile = true;
create.eMode = FS::EFileOpenMode::eReadWrite;
create.eAdvisoryLevel = FS::EFileAdvisoryLockLevel::eBlockReadWrite;
return AuMove(create);
}
cstatic HandleCreate ReadWrite(const AuString &path)
{
HandleCreate create(path);
create.eMode = FS::EFileOpenMode::eReadWrite;
create.eAdvisoryLevel = FS::EFileAdvisoryLockLevel::eBlockReadWrite;
return AuMove(create);
}
cstatic HandleCreate Read(const AuString &path)
{
HandleCreate read(path);
read.eMode = FS::EFileOpenMode::eRead;
read.eAdvisoryLevel = FS::EFileAdvisoryLockLevel::eBlockWrite;
return AuMove(read);
}
cstatic HandleCreate Open(const AuString &path)
{
HandleCreate read(path);
read.eMode = FS::EFileOpenMode::eRead;
read.eAdvisoryLevel = FS::EFileAdvisoryLockLevel::eBlockReadWrite;
return AuMove(read);
}
inline HandleCreate(const AuString &path) :
path(path)
{
}
};
virtual bool InitFromHandle(AuSPtr<IIOHandle> pHandle) = 0;
virtual bool InitFromPath(HandleCreate create) = 0;
virtual bool InitFromCopy(AuUInt64 uOSHandle) = 0;
virtual bool InitFromMove(AuUInt64 uOSHandle) = 0;
virtual bool InitFromPair(AuUInt64 uOSReadHandle, AuUInt64 uOSWriteHandle) = 0;
virtual bool InitFromPairMove(AuOptionalEx<AuUInt64> uOSReadHandle,
AuOptionalEx<AuUInt64> uOSWriteHandle) = 0;
virtual AuUInt64 GetOSHandle() = 0;
virtual AuUInt64 GetOSReadHandle() = 0;
virtual AuOptionalEx<AuUInt64> GetOSReadHandleSafe() = 0;
virtual AuUInt64 GetOSWriteHandle() = 0;
virtual AuOptionalEx<AuUInt64> GetOSWriteHandleSafe() = 0;
virtual bool IsValid() = 0;
virtual bool HasUniqueWriteHandle() = 0;
virtual bool IsAsync() = 0;
virtual AuString GetPath() = 0;
};
AUKN_SHARED_SOO(IOHandle, IIOHandle, 256);
}

View File

@ -124,7 +124,7 @@ namespace Aurora::Memory
{
if (buffer.length)
{
this->base = FAlloc<AuUInt8 *>(buffer.length);
this->base = ZAlloc<AuUInt8 *>(buffer.length);
}
this->scaleSize = buffer.scaleSize;
this->flagCircular = buffer.flagCircular;
@ -160,7 +160,7 @@ namespace Aurora::Memory
inline ByteBuffer(const void *in, AuUInt length, bool circular = false, bool expandable = false) : flagCircular(circular), flagExpandable(expandable), flagReadError(0), flagWriteError(0)
{
this->scaleSize = kBufferInitialPower;
this->base = length ? FAlloc<AuUInt8 *>(length) : nullptr;
this->base = length ? ZAlloc<AuUInt8 *>(length) : nullptr;
if (!this->base)
{
Reset();
@ -181,7 +181,7 @@ namespace Aurora::Memory
inline ByteBuffer(const AuList<AuUInt8> &vector, bool circular = false, bool expandable = false) : flagCircular(circular), flagExpandable(expandable), flagReadError(0), flagWriteError(0)
{
this->scaleSize = kBufferInitialPower;
this->base = vector.size() ? FAlloc<AuUInt8 *>(vector.size()) : nullptr;
this->base = vector.size() ? ZAlloc<AuUInt8 *>(vector.size()) : nullptr;
if (!this->base)
{
Reset();

View File

@ -31,7 +31,7 @@ namespace Aurora::Memory
return true;
}
this->base = fast ? FAlloc<AuUInt8 *>(length) : ZAlloc<AuUInt8 *>(length);
this->base = ZAlloc<AuUInt8 *>(length);
if (!this->base)
{
return false;
@ -65,7 +65,7 @@ namespace Aurora::Memory
return true;
}
this->base = fast ? FAlloc<AuUInt8 *>(length, alignment) : ZAlloc<AuUInt8 *>(length, alignment);
this->base = ZAlloc<AuUInt8 *>(length, alignment);
if (!this->base)
{
return false;

260
Source/IO/AuIOHandle.NT.cpp Normal file
View File

@ -0,0 +1,260 @@
/***
Copyright (C) 2023 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: AuIOHandle.NT.cpp
Date: 2023-7-28
Author: Reece
***/
#include <RuntimeInternal.hpp>
#include "AuIOHandle.hpp"
#include "AuIOHandle.NT.hpp"
#include "FS/FS.hpp"
#include "FS/FileAdvisory.NT.hpp"
namespace Aurora::IO
{
AuUInt64 AFileHandle::DupHandle(AuUInt64 uOSHandle, bool bWriteAccess)
{
HANDLE hTargetHandle = (HANDLE)uOSHandle;
HANDLE hTargetProcess = ::GetCurrentProcess();
HANDLE hHandle {};
if (!::DuplicateHandle(hTargetProcess,
hTargetHandle,
hTargetProcess,
&hHandle,
bWriteAccess ? GENERIC_WRITE | GENERIC_READ : GENERIC_READ,
FALSE,
FALSE))
{
return 0;
}
return AuUInt64(hHandle);
}
void AFileHandle::CloseHandle(AuUInt64 uOSHandle)
{
HANDLE hHandle = (HANDLE)uOSHandle;
AuWin32CloseHandle(hHandle);
}
struct NTIOHandle final : AFileHandle
{
bool InitFromPath(HandleCreate create) override
{
HANDLE hFileHandle;
DWORD dwFlags {};
DWORD dwShare {};
if (create.path.empty())
{
SysPushErrorArg("Cannot open an IO handle to the provided empty path");
return false;
}
if (!FS::EFileOpenModeIsValid(create.eMode))
{
SysPushErrorParam("Invalid open mode");
return false;
}
if (!FS::EFileAdvisoryLockLevelIsValid(create.eAdvisoryLevel))
{
SysPushErrorParam("Invalid lock mode");
return false;
}
auto pathex = FS::NormalizePathRet(create.path);
if (pathex.empty())
{
SysPushErrorMemory();
return false;
}
auto win32Path = Locale::ConvertFromUTF8(pathex);
if (win32Path.empty())
{
SysPushErrorMemory();
return false;
}
hFileHandle = INVALID_HANDLE_VALUE;
dwShare = FS::NtLockAdvisoryToShare(create.eAdvisoryLevel);
if (create.bAsyncHandle)
{
dwFlags |= FILE_FLAG_OVERLAPPED;
}
if (create.bDirectIOMode)
{
dwFlags |= FILE_FLAG_NO_BUFFERING;
}
if (!dwFlags)
{
dwFlags |= FILE_ATTRIBUTE_NORMAL;
}
switch (create.eMode)
{
case FS::EFileOpenMode::eRead:
{
hFileHandle = ::CreateFileW(win32Path.c_str(),
GENERIC_READ,
dwShare,
NULL,
OPEN_EXISTING,
dwFlags,
NULL);
if (hFileHandle != INVALID_HANDLE_VALUE)
{
this->uOSReadHandle = AuUInt64(hFileHandle);
}
break;
}
case FS::EFileOpenMode::eReadWrite:
{
if (create.bAlwaysCreateDirTree)
{
FS::CreateDirectories(pathex, true);
}
if (create.bFailIfNonEmptyFile)
{
hFileHandle = ::CreateFileW(win32Path.c_str(),
GENERIC_WRITE | GENERIC_READ | DELETE,
NULL,
NULL,
CREATE_NEW,
dwFlags,
NULL);
if (hFileHandle == INVALID_HANDLE_VALUE)
{
if (AuFS::FileExists(pathex.c_str()))
{
SysPushErrorResourceExists("File {} already exists", create.path);
return false;
}
}
}
else
{
hFileHandle = ::CreateFileW(win32Path.c_str(),
GENERIC_WRITE | GENERIC_READ | DELETE,
dwShare,
NULL,
OPEN_EXISTING,
dwFlags,
NULL);
if (hFileHandle == INVALID_HANDLE_VALUE)
{
hFileHandle = ::CreateFileW(win32Path.c_str(),
GENERIC_WRITE | GENERIC_READ | DELETE,
dwShare,
NULL,
CREATE_NEW,
dwFlags,
NULL);
}
}
if (hFileHandle != INVALID_HANDLE_VALUE)
{
this->uOSReadHandle = AuUInt64(hFileHandle);
this->uOSWriteHandle = AuUInt64(hFileHandle);
}
break;
}
case FS::EFileOpenMode::eWrite:
{
if (create.bAlwaysCreateDirTree)
{
FS::CreateDirectories(pathex, true);
}
if (create.bFailIfNonEmptyFile)
{
hFileHandle = ::CreateFileW(win32Path.c_str(),
GENERIC_WRITE | DELETE,
NULL,
NULL,
CREATE_NEW,
dwFlags,
NULL);
if (hFileHandle == INVALID_HANDLE_VALUE)
{
if (AuFS::FileExists(pathex.c_str()))
{
SysPushErrorResourceExists("File {} already exists", create.path);
return false;
}
}
}
else
{
hFileHandle = ::CreateFileW(win32Path.c_str(),
GENERIC_WRITE | FILE_READ_ATTRIBUTES | DELETE,
dwShare,
NULL,
OPEN_EXISTING,
dwFlags,
NULL);
if (hFileHandle == INVALID_HANDLE_VALUE)
{
hFileHandle = ::CreateFileW(win32Path.c_str(),
GENERIC_WRITE | DELETE,
dwShare,
NULL,
CREATE_NEW,
dwFlags,
NULL);
}
}
if (hFileHandle != INVALID_HANDLE_VALUE)
{
this->uOSWriteHandle = AuUInt64(hFileHandle);
}
break;
}
}
if (hFileHandle == INVALID_HANDLE_VALUE)
{
SysPushErrorIO("Couldn't open: {}", create.path);
return false;
}
this->bIsAsync = create.bAsyncHandle;
this->path = create.path;
return this->IsValid();
}
};
AUKN_SYM IIOHandle *IOHandleNew()
{
return _new NTIOHandle();
}
AUKN_SYM void IOHandleRelease(IIOHandle *pIOHandle)
{
AuSafeDelete<NTIOHandle *>(pIOHandle);
}
AUROXTL_INTERFACE_SOO_SRC_EX(AURORA_SYMBOL_EXPORT, IOHandle, NTIOHandle)
}

View File

@ -0,0 +1,13 @@
/***
Copyright (C) 2023 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: AuIOHandle.NT.hpp
Date: 2023-7-28
Author: Reece
***/
#pragma once
namespace Aurora::IO
{
}

174
Source/IO/AuIOHandle.cpp Normal file
View File

@ -0,0 +1,174 @@
/***
Copyright (C) 2023 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: AuIOHandle.cpp
Date: 2023-7-28
Author: Reece
***/
#include <RuntimeInternal.hpp>
#include "AuIOHandle.hpp"
namespace Aurora::IO
{
AFileHandle::~AFileHandle()
{
if (this->uOSWriteHandle.HasValue() && this->uOSReadHandle.HasValue() &&
this->uOSReadHandle.Value() == this->uOSWriteHandle.Value())
{
this->CloseHandle(this->uOSReadHandle.value());
AuResetMember(this->uOSReadHandle);
AuResetMember(this->uOSWriteHandle);
}
if (this->uOSReadHandle)
{
this->CloseHandle(this->uOSReadHandle.value());
AuResetMember(this->uOSReadHandle);
}
if (this->uOSWriteHandle)
{
this->CloseHandle(this->uOSWriteHandle.value());
AuResetMember(this->uOSWriteHandle);
}
}
bool AFileHandle::InitFromHandle(AuSPtr<IIOHandle> pHandle)
{
auto pSrc = AuStaticCast<AFileHandle>(pHandle);
auto pDest = this;
if (this->IsValid())
{
return false;
}
pDest->pThat = pHandle;
pDest->uOSReadHandle = pSrc->uOSReadHandle;
pDest->uOSWriteHandle = pSrc->uOSWriteHandle;
pDest->bIsAsync = pSrc->bIsAsync;
return true;
}
bool AFileHandle::InitFromCopy(AuUInt64 uOSHandle)
{
if (this->IsValid())
{
return false;
}
if (auto uOSWriteHandle = this->DupHandle(uOSHandle, true))
{
this->uOSReadHandle = uOSWriteHandle;
this->uOSWriteHandle = uOSWriteHandle;
return true;
}
else
{
return {};
}
}
bool AFileHandle::InitFromMove(AuUInt64 uOSHandle)
{
if (this->IsValid())
{
return false;
}
this->uOSReadHandle = uOSHandle;
this->uOSWriteHandle = uOSHandle;
return true;
}
bool AFileHandle::InitFromPair(AuUInt64 uOSReadHandle,
AuUInt64 uOSWriteHandle)
{
if (this->IsValid())
{
return false;
}
if (auto uOSReadHandle2 = this->DupHandle(uOSReadHandle, false))
{
this->uOSReadHandle = uOSReadHandle2;
}
else
{
return {};
}
if (auto uOSWriteHandle2 = this->DupHandle(uOSWriteHandle, true))
{
this->uOSWriteHandle = uOSWriteHandle2;
}
else
{
this->CloseHandle(this->uOSReadHandle);
AuResetMember(this->uOSReadHandle);
return {};
}
return true;
}
bool AFileHandle::InitFromPairMove(AuOptionalEx<AuUInt64> uOSReadHandle,
AuOptionalEx<AuUInt64> uOSWriteHandle)
{
if (this->IsValid())
{
return false;
}
this->uOSReadHandle = uOSReadHandle;
this->uOSWriteHandle = uOSWriteHandle;
return true;
}
AuUInt64 AFileHandle::GetOSHandle()
{
return this->uOSReadHandle.ValueOr(this->uOSWriteHandle.Value());
}
AuUInt64 AFileHandle::GetOSReadHandle()
{
return this->uOSReadHandle.value();
}
AuOptionalEx<AuUInt64> AFileHandle::GetOSReadHandleSafe()
{
return this->uOSReadHandle;
}
AuUInt64 AFileHandle::GetOSWriteHandle()
{
return this->uOSWriteHandle.Value();
}
AuOptionalEx<AuUInt64> AFileHandle::GetOSWriteHandleSafe()
{
return this->uOSWriteHandle;
}
bool AFileHandle::IsValid()
{
return this->uOSReadHandle.HasValue() ||
this->uOSWriteHandle.HasValue();
}
bool AFileHandle::HasUniqueWriteHandle()
{
return this->uOSWriteHandle.HasValue();
}
bool AFileHandle::IsAsync()
{
return this->bIsAsync;
}
AuString AFileHandle::GetPath()
{
return this->path;
}
}

60
Source/IO/AuIOHandle.hpp Normal file
View File

@ -0,0 +1,60 @@
/***
Copyright (C) 2023 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: AuIOHandle.hpp
Date: 2023-7-28
Author: Reece
***/
#pragma once
namespace Aurora::IO
{
struct AFileHandle : IIOHandle
{
virtual ~AFileHandle();
bool InitFromHandle(AuSPtr<IIOHandle> pHandle) override;
bool InitFromCopy(AuUInt64 uOSHandle) override;
bool InitFromMove(AuUInt64 uOSHandle) override;
bool InitFromPair(AuUInt64 uOSReadHandle,
AuUInt64 uOSWriteHandle) override;
bool InitFromPairMove(AuOptionalEx<AuUInt64> uOSReadHandle,
AuOptionalEx<AuUInt64> uOSWriteHandle) override;
AuUInt64 GetOSHandle() override;
AuUInt64 GetOSReadHandle() override;
AuOptionalEx<AuUInt64> GetOSReadHandleSafe() override;
AuUInt64 GetOSWriteHandle() override;
AuOptionalEx<AuUInt64> GetOSWriteHandleSafe() override;
bool IsValid() override;
bool HasUniqueWriteHandle() override;
bool IsAsync() override;
AuString GetPath() override;
AuOptionalEx<AuUInt64> uOSWriteHandle;
AuOptionalEx<AuUInt64> uOSReadHandle;
AuSPtr<IIOHandle> pThat;
bool bIsAsync {};
AuString path;
protected:
// Implement me:
// bool InitFromPath(HandleCreate create) override;
static AuUInt64 DupHandle(AuUInt64 uOSHandle, bool bWriteAccess);
static void CloseHandle(AuUInt64 uOSHandle);
};
}

View File

@ -62,105 +62,14 @@ namespace Aurora::IO::FS
AuWin32CloseHandle(this->event);
}
FileHandle::~FileHandle()
AuSPtr<IIOHandle> NtAsyncFileStream::GetHandle()
{
if (this->bNoOwns)
{
return;
}
if (this->writeHandle != this->handle)
{
AuWin32CloseHandle(this->writeHandle);
}
this->writeHandle = INVALID_HANDLE_VALUE;
AuWin32CloseHandle(this->handle);
return this->pHandle_;
}
bool FileHandle::Init(const AuString &path, EFileOpenMode openMode, bool directIO, EFileAdvisoryLockLevel lock)
void NtAsyncFileStream::Init(const AuSPtr<IIOHandle> &pHandle)
{
HANDLE fileHandle;
auto pathex = NormalizePathRet(path);
if (pathex.empty())
{
return false;
}
auto win32Path = Locale::ConvertFromUTF8(pathex);
if (win32Path.empty())
{
return false;
}
auto flags = FILE_FLAG_OVERLAPPED;
if (directIO)
{
flags |= FILE_FLAG_NO_BUFFERING;
}
fileHandle = INVALID_HANDLE_VALUE;
switch (openMode)
{
case EFileOpenMode::eRead:
{
fileHandle = CreateFileW(win32Path.c_str(), GENERIC_READ, NtLockAdvisoryToShare(lock), NULL, OPEN_EXISTING, flags, NULL);
break;
}
case EFileOpenMode::eReadWrite:
{
CreateDirectories(pathex, true);
fileHandle = CreateFileW(win32Path.c_str(), GENERIC_WRITE | GENERIC_READ, NtLockAdvisoryToShare(lock), NULL, OPEN_ALWAYS, flags, NULL);
if (fileHandle == INVALID_HANDLE_VALUE)
{
fileHandle = CreateFileW(win32Path.c_str(), GENERIC_WRITE | GENERIC_READ, NtLockAdvisoryToShare(lock), NULL, CREATE_ALWAYS, flags, NULL);
}
break;
}
case EFileOpenMode::eWrite:
{
CreateDirectories(pathex, true);
fileHandle = CreateFileW(win32Path.c_str(), GENERIC_WRITE | FILE_READ_ATTRIBUTES, NtLockAdvisoryToShare(lock), NULL, OPEN_ALWAYS, flags, NULL);
if (fileHandle == INVALID_HANDLE_VALUE)
{
fileHandle = CreateFileW(win32Path.c_str(), GENERIC_WRITE | GENERIC_READ, NtLockAdvisoryToShare(lock), NULL, CREATE_ALWAYS, flags, NULL);
}
break;
}
}
if (fileHandle == INVALID_HANDLE_VALUE)
{
SysPushErrorIO("Missing file: {}", path);
return {};
}
this->directIO = directIO;
this->handle = fileHandle;
this->writeHandle = fileHandle;
this->readOnly = openMode == EFileOpenMode::eRead;
return true;
}
void FileHandle::Init(HANDLE read, HANDLE write)
{
this->directIO = true;
this->handle = read;
this->writeHandle = write;
this->readOnly = false;
}
AuSPtr<FileHandle> NtAsyncFileStream::GetHandle()
{
return handle_;
}
void NtAsyncFileStream::Init(const AuSPtr<FileHandle> &handle)
{
this->handle_ = handle;
this->pHandle_ = pHandle;
}
AuSPtr<IAsyncTransaction> NtAsyncFileStream::NewTransaction()
@ -171,7 +80,7 @@ namespace Aurora::IO::FS
return {};
}
if (!shared->Init(this->handle_))
if (!shared->InitWeak(this->pHandle_))
{
return {};
}
@ -184,13 +93,15 @@ namespace Aurora::IO::FS
LARGE_INTEGER i {};
i.QuadPart = length;
if (!SetFilePointerEx(this->handle_->handle, i, nullptr, FILE_BEGIN))
auto hHandle = (HANDLE)this->pHandle_->GetOSHandle();
if (!SetFilePointerEx(hHandle, i, nullptr, FILE_BEGIN))
{
SysPushErrorIO();
return false;
}
return SetEndOfFile(this->handle_->handle);
return SetEndOfFile(hHandle);
}
bool NtAsyncFileStream::BlockingRead(AuUInt64 offset, const Memory::MemoryViewStreamWrite &parameters)
@ -198,12 +109,15 @@ namespace Aurora::IO::FS
LARGE_INTEGER i {};
i.QuadPart = offset;
if (this->handle_->bReadLock)
auto hOptSafe = this->pHandle_->GetOSReadHandleSafe();
if (!hOptSafe)
{
return false;
}
if (!SetFilePointerEx(this->handle_->handle, i, nullptr, FILE_BEGIN))
auto hHandle = (HANDLE)hOptSafe.Value();
if (!SetFilePointerEx(hHandle, i, nullptr, FILE_BEGIN))
{
SysPushErrorIO();
return false;
@ -213,7 +127,7 @@ namespace Aurora::IO::FS
a.hEvent = CreateEventA(NULL, true, 0, NULL);
DWORD read;
if (!::ReadFile(this->handle_->handle, parameters.ptr, parameters.length, NULL, &a) &&
if (!::ReadFile(hHandle, parameters.ptr, parameters.length, NULL, &a) &&
::GetLastError() != ERROR_IO_PENDING)
{
SysPushErrorIO();
@ -222,7 +136,7 @@ namespace Aurora::IO::FS
}
::WaitForSingleObject(a.hEvent, 0);
if (!::GetOverlappedResult(this->handle_->handle, &a, &read, true))
if (!::GetOverlappedResult(hHandle, &a, &read, true))
{
::CloseHandle(a.hEvent);
return false;
@ -238,12 +152,15 @@ namespace Aurora::IO::FS
LARGE_INTEGER i {};
i.QuadPart = offset;
if (this->handle_->bWriteLock)
auto hOptSafe = this->pHandle_->GetOSWriteHandleSafe();
if (!hOptSafe)
{
return false;
}
if (!SetFilePointerEx(this->handle_->handle, i, nullptr, FILE_BEGIN))
auto hHandle = (HANDLE)hOptSafe.Value();
if (!SetFilePointerEx(hHandle, i, nullptr, FILE_BEGIN))
{
SysPushErrorIO();
return false;
@ -253,7 +170,7 @@ namespace Aurora::IO::FS
a.hEvent = CreateEventA(NULL, true, 0, NULL);
DWORD read;
if (!::WriteFile(this->handle_->writeHandle, parameters.ptr, parameters.length, NULL, &a) &&
if (!::WriteFile(hHandle, parameters.ptr, parameters.length, NULL, &a) &&
::GetLastError() != ERROR_IO_PENDING)
{
SysPushErrorIO();
@ -262,7 +179,7 @@ namespace Aurora::IO::FS
}
::WaitForSingleObject(a.hEvent, 0);
if (!::GetOverlappedResult(this->handle_->writeHandle, &a, &read, true))
if (!::GetOverlappedResult(hHandle, &a, &read, true))
{
::CloseHandle(a.hEvent);
return false;
@ -273,7 +190,14 @@ namespace Aurora::IO::FS
return true;
}
bool NtAsyncFileTransaction::Init(const AuSPtr<FileHandle> &handle)
bool NtAsyncFileTransaction::InitWeak(const AuSPtr<IIOHandle> &handle)
{
this->wpHandle_ = handle;
this->overlap.hEvent = this->event = CreateEventW(nullptr, true, false, nullptr);
return this->overlap.hEvent != INVALID_HANDLE_VALUE;
}
bool NtAsyncFileTransaction::Init(const AuSPtr<IIOHandle> &handle)
{
this->pHandle_ = handle;
this->overlap.hEvent = this->event = CreateEventW(nullptr, true, false, nullptr);
@ -292,8 +216,7 @@ namespace Aurora::IO::FS
auto er = GetLastError();
if (val)
{
::SetEvent(that->event);
that->DispatchCb(that->dwLastAbstractStat);
//(void)that->Complete();
return true;
}
else if (er == ERROR_IO_PENDING)
@ -309,7 +232,7 @@ namespace Aurora::IO::FS
that->bHasFailed = true; // to pass completion
that->dwOsErrorCode = er; // to suppress actual error condition
auto pipe = that->pNtIpcPipeImpl.lock();
auto pipe = AuTryLockMemoryType(that->pNtIpcPipeImpl);
that->DispatchCb(0);
@ -319,6 +242,7 @@ namespace Aurora::IO::FS
}
that->pMemoryHold.reset();
that->pPin.reset();
return true;
}
else
@ -327,7 +251,7 @@ namespace Aurora::IO::FS
that->Reset();
that->dwOsErrorCode = er;
that->bHasFailed = true;
SysPushErrorFIO("QoA async FIO error: {} {}", that->GetFileHandle()->path, that->dwOsErrorCode);
SysPushErrorFIO("QoA async FIO error: {} {}", /*that->GetFileHandle()->path*/ "", that->dwOsErrorCode);
return false;
}
}
@ -340,6 +264,11 @@ namespace Aurora::IO::FS
auto transaction = reinterpret_cast<NtAsyncFileTransaction *>(reinterpret_cast<AuUInt8*>(lpOverlapped) - offsetof(NtAsyncFileTransaction, overlap));
auto hold = AuExchange(transaction->pPin, {});
if (!hold)
{
return;
}
if (dwErrorCode)
{
hold->bHasFailed = true;
@ -399,7 +328,12 @@ namespace Aurora::IO::FS
return {};
}
if (this->pHandle_->bReadLock)
auto pHandle = this->GetFileHandle();
auto optRead = pHandle->GetOSReadHandleSafe();
if (!optRead)
{
return false;
}
@ -418,7 +352,7 @@ namespace Aurora::IO::FS
this->overlap.Offset = AuBitsToLower(offset);
this->overlap.OffsetHigh = AuBitsToHigher(offset);
auto ret = ::ReadFileEx(this->pHandle_->handle, memoryView->ptr, memoryView->length, &this->overlap, FileOperationCompletion);
auto ret = ::ReadFileEx((HANDLE)optRead.value(), memoryView->ptr, memoryView->length, &this->overlap, FileOperationCompletion);
return TranslateNtStatus(this, ret);
}
@ -447,7 +381,11 @@ namespace Aurora::IO::FS
return {};
}
if (this->pHandle_->bWriteLock)
auto pHandle = this->GetFileHandle();
auto optWrite = pHandle->GetOSWriteHandleSafe();
if (!optWrite)
{
return false;
}
@ -465,7 +403,7 @@ namespace Aurora::IO::FS
this->ResetAIO();
this->overlap.Offset = AuBitsToLower(offset);
this->overlap.OffsetHigh = AuBitsToHigher(offset);
auto ret = ::WriteFileEx(this->pHandle_->writeHandle, memoryView->ptr, memoryView->length, &this->overlap, FileOperationCompletion);
auto ret = ::WriteFileEx((HANDLE)optWrite.value(), memoryView->ptr, memoryView->length, &this->overlap, FileOperationCompletion);
return TranslateNtStatus(this, ret);
}
@ -493,14 +431,22 @@ namespace Aurora::IO::FS
{
this->isIrredeemable_ = true;
this->bHasFailed = true;
if (pCancelIoEx)
auto hOptSafe = this->GetFileHandle()->GetOSReadHandleSafe();
if (hOptSafe)
{
pCancelIoEx(this->pHandle_->handle, &this->overlap);
}
else
{
::CancelIo(this->pHandle_->handle);
auto hHandle = (HANDLE)hOptSafe.Value();
if (pCancelIoEx)
{
pCancelIoEx(hHandle, &this->overlap);
}
else
{
::CancelIo(hHandle);
}
}
::SetEvent(this->event);
this->dwOsErrorCode = ERROR_ABANDONED_WAIT_0;
}
@ -540,13 +486,20 @@ namespace Aurora::IO::FS
if (!completeRoutine)
{
if (::GetOverlappedResult(this->pHandle_->handle,
&this->overlap,
&read,
false) && (read || bForce))
auto hOptSafe = this->GetFileHandle()->GetOSReadHandleSafe();
if (hOptSafe)
{
DispatchCb(read);
return true;
auto hHandle = (HANDLE)hOptSafe.Value();
if (::GetOverlappedResult(hHandle,
&this->overlap,
&read,
false) && (read || bForce))
{
SetEvent(this->overlap.hEvent);
DispatchCb(read);
return true;
}
}
}
else
@ -572,7 +525,7 @@ namespace Aurora::IO::FS
}
return bool(this->dwLastBytes) ||
this->Failed();
this->bHasFailed;
}
bool NtAsyncFileTransaction::Complete()
@ -616,9 +569,9 @@ namespace Aurora::IO::FS
return this->event;
}
AuSPtr<FileHandle> NtAsyncFileTransaction::GetFileHandle()
AuSPtr<IIOHandle> NtAsyncFileTransaction::GetFileHandle()
{
return this->pHandle_;
return this->pHandle_ ? this->pHandle_ : AuTryLockMemoryType(this->wpHandle_);
}
AuSPtr<AuLoop::ILoopSource> NtAsyncFileTransaction::NewLoopSource()
@ -628,36 +581,34 @@ namespace Aurora::IO::FS
AUKN_SYM IAsyncFileStream *OpenAsyncNew(const AuString &path, EFileOpenMode openMode, bool directIO, EFileAdvisoryLockLevel lock)
{
AuSPtr<FileHandle> fileHandle;
NtAsyncFileStream *stream;
if (path.empty())
auto pHandle = AuIO::IOHandleShared();
if (!pHandle)
{
SysPushErrorParam("Empty path");
return {};
SysPushErrorMemory();
return nullptr;
}
if (!EFileOpenModeIsValid(openMode))
AuIO::IIOHandle::HandleCreate createhandle(path);
createhandle.eAdvisoryLevel = lock;
createhandle.eMode = openMode;
createhandle.bFailIfNonEmptyFile = false;
createhandle.bDirectIOMode = directIO;
createhandle.bAsyncHandle = true;
if (!pHandle->InitFromPath(createhandle))
{
SysPushErrorParam("Invalid open mode");
return {};
return nullptr;
}
fileHandle = AuMakeShared<FileHandle>();
if (!fileHandle->Init(path, openMode, directIO, lock))
auto pStream = _new NtAsyncFileStream();
if (!pStream)
{
return {};
SysPushErrorMemory();
return nullptr;
}
stream = _new NtAsyncFileStream();
if (!stream)
{
return {};
}
stream->Init(fileHandle);
return stream;
pStream->Init(pHandle);
return pStream;
}
AUKN_SYM void OpenAsyncRelease(IAsyncFileStream *handle)

View File

@ -14,22 +14,6 @@ namespace Aurora::IO::IPC
namespace Aurora::IO::FS
{
struct FileHandle
{
~FileHandle();
bool Init(const AuString &path, EFileOpenMode openMode, bool directIO, EFileAdvisoryLockLevel lock);
void Init(HANDLE read, HANDLE write);
HANDLE handle {INVALID_HANDLE_VALUE}, writeHandle {INVALID_HANDLE_VALUE};
AuString path;
bool readOnly;
bool directIO;
bool bNoOwns { false };
bool bWriteLock { false };
bool bReadLock { false };
};
struct NtAsyncFileStream : IAsyncFileStream
{
AuSPtr<IAsyncTransaction> NewTransaction() override;
@ -38,19 +22,20 @@ namespace Aurora::IO::FS
bool BlockingRead(AuUInt64 offset, const Memory::MemoryViewStreamWrite &parameters) override;
bool BlockingWrite(AuUInt64 offset, const Memory::MemoryViewStreamRead &parameters) override;
void Init(const AuSPtr<FileHandle> &handle);
void Init(const AuSPtr<IIOHandle> &pHandle);
AuSPtr<FileHandle> GetHandle();
AuSPtr<IIOHandle> GetHandle();
private:
AuSPtr<FileHandle> handle_;
AuSPtr<IIOHandle> pHandle_;
};
struct NtAsyncFileTransaction : IAsyncTransaction, AuEnableSharedFromThis<NtAsyncFileTransaction>
{
~NtAsyncFileTransaction();
bool Init(const AuSPtr<FileHandle> &handle);
bool Init(const AuSPtr<IIOHandle> &handle);
bool InitWeak(const AuSPtr<IIOHandle> &handle);
void ResetAIO();
bool StartRead(AuUInt64 offset, const AuSPtr<AuMemoryViewWrite> &memoryView) override;
@ -78,7 +63,7 @@ namespace Aurora::IO::FS
void DispatchCb(AuUInt32 len);
HANDLE GetHandle();
AuSPtr<FileHandle> GetFileHandle();
AuSPtr<IIOHandle> GetFileHandle();
OVERLAPPED overlap {};
HANDLE event = INVALID_HANDLE_VALUE;
@ -94,7 +79,8 @@ namespace Aurora::IO::FS
AuSPtr<void> pMemoryHold;
private:
AuSPtr<FileHandle> pHandle_;
AuSPtr<IIOHandle> pHandle_;
AuWPtr<IIOHandle> wpHandle_;
AuSPtr<IAsyncFinishedSubscriber> pSub_;
};
}

View File

@ -14,17 +14,16 @@
namespace Aurora::IO::FS
{
static const AuUInt64 kFileCopyBlock = 0xFFFF; // 64KiB, 1k iterations to max out 64MB/s disk, 2k iteration to make out 128MB/s disk, is this number still way too low? cpu go brr
static const AuUInt64 kFileCopyBlock = 0xFFFF * 128;
WinFileStream::~WinFileStream()
{
Close();
}
void WinFileStream::Init(HANDLE handle, const AuString &path)
void WinFileStream::Init(AuSPtr<IIOHandle> pHandle)
{
this->handle_ = handle;
this->path_ = path;
this->pHandle_ = pHandle;
}
AuUInt64 WinFileStream::GetOffset()
@ -32,16 +31,20 @@ namespace Aurora::IO::FS
LARGE_INTEGER distance {};
LARGE_INTEGER pos {};
if (this->handle_ == INVALID_HANDLE_VALUE)
auto hHandle = this->GetHandle();
if (hHandle == INVALID_HANDLE_VALUE)
{
SysPushErrorUninitialized();
return 0;
}
if (SetFilePointerEx(this->handle_, distance, &pos, FILE_CURRENT) == INVALID_SET_FILE_POINTER)
if (::SetFilePointerEx(hHandle,
distance,
&pos,
FILE_CURRENT) == INVALID_SET_FILE_POINTER)
{
AuLogWarn("SetFilePointerEx IO Error: 0x{:x}, {}", GetLastError(), path_);
SysPushErrorIO();
SysPushErrorIO("SetFilePointerEx IO Error: 0x{:x}, {}", GetLastError(), this->pHandle_ ? this->pHandle_->GetPath() : "");
return 0;
}
@ -53,7 +56,9 @@ namespace Aurora::IO::FS
LARGE_INTEGER distance {};
LARGE_INTEGER pos {};
if (this->handle_ == INVALID_HANDLE_VALUE)
auto hHandle = this->GetHandle();
if (hHandle == INVALID_HANDLE_VALUE)
{
SysPushErrorUninitialized();
return false;
@ -61,10 +66,9 @@ namespace Aurora::IO::FS
distance.QuadPart = offset;
if (SetFilePointerEx(this->handle_, distance, &pos, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
if (::SetFilePointerEx(hHandle, distance, &pos, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
{
AuLogWarn("SetFilePointerEx IO Error: 0x{:x}, {}", GetLastError(), path_);
SysPushErrorIO();
SysPushErrorIO("SetFilePointerEx IO Error: 0x{:x}, {}", GetLastError(), this->pHandle_ ? this->pHandle_->GetPath() : "");
return false;
}
@ -74,14 +78,16 @@ namespace Aurora::IO::FS
AuUInt64 WinFileStream::GetLength()
{
LARGE_INTEGER length;
auto hHandle = this->GetHandle();
if (handle_ == INVALID_HANDLE_VALUE)
if (hHandle == INVALID_HANDLE_VALUE)
{
SysPushErrorUninitialized();
return 0;
}
if (!GetFileSizeEx(this->handle_, &length))
if (!::GetFileSizeEx(hHandle, &length))
{
SysPushErrorIO();
return 0;
@ -92,113 +98,218 @@ namespace Aurora::IO::FS
bool WinFileStream::Read(const Memory::MemoryViewStreamWrite &parameters)
{
if (this->handle_ == INVALID_HANDLE_VALUE)
auto hHandle = this->GetHandle();
HANDLE hEventHandle { INVALID_HANDLE_VALUE };
if (hHandle == INVALID_HANDLE_VALUE)
{
SysPushErrorUninitialized();
return {};
}
auto length = parameters.length;
bool bIsAsync = this->pHandle_->IsAsync();
if (bIsAsync)
{
hEventHandle = ::CreateEventA(nullptr, false, false, nullptr);
}
parameters.outVariable = 0;
AuUInt64 offset {0};
while (length)
AuUInt64 uLength = parameters.length;
AuUInt64 uOffset {};
while (uLength)
{
DWORD read;
int blockSize = AuMin(AuUInt(kFileCopyBlock), length);
auto blockSize = AuMin(AuUInt(kFileCopyBlock), uLength);
if (!::ReadFile(this->handle_, reinterpret_cast<char *>(parameters.ptr) + offset, blockSize, &read, NULL))
if (this->pHandle_->IsAsync())
{
AuLogWarn("ReadFile IO Error: 0x{:x}, {}", GetLastError(), path_);
SysPushErrorIO();
return false;
OVERLAPPED overlapped {};
overlapped.hEvent = hEventHandle;
if (!::ReadFile(hHandle,
reinterpret_cast<char *>(parameters.ptr) + uOffset,
blockSize,
NULL,
&overlapped) &&
::GetLastError() != ERROR_IO_PENDING)
{
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))
{
AuWin32CloseHandle(hEventHandle);
parameters.outVariable = uOffset;
return false;
}
::CloseHandle(hEventHandle);
}
else
{
if (!::ReadFile(hHandle,
reinterpret_cast<char *>(parameters.ptr) + uOffset,
blockSize,
&read,
NULL))
{
SysPushErrorIO("ReadFile IO Error: 0x{:x}, {}", GetLastError(), this->pHandle_ ? this->pHandle_->GetPath() : "");
AuWin32CloseHandle(hEventHandle);
parameters.outVariable = uOffset;
return false;
}
}
if (read == 0)
{
break;
}
offset += read;
length -= read;
uOffset += read;
uLength -= read;
}
parameters.outVariable = offset;
AuWin32CloseHandle(hEventHandle);
parameters.outVariable = uOffset;
return true;
}
bool WinFileStream::Write(const Memory::MemoryViewStreamRead &parameters)
{
if (this->handle_ == INVALID_HANDLE_VALUE)
auto hHandle = this->GetHandle();
HANDLE hEventHandle { INVALID_HANDLE_VALUE };
if (hHandle == INVALID_HANDLE_VALUE)
{
SysPushErrorUninitialized();
return 0;
}
auto length = parameters.length;
bool bIsAsync = this->pHandle_->IsAsync();
if (bIsAsync)
{
hEventHandle = ::CreateEventA(nullptr, false, false, nullptr);
}
parameters.outVariable = 0;
AuUInt offset {0};
while (length)
AuUInt64 uLength = parameters.length;
AuUInt64 uOffset {};
while (uLength)
{
DWORD written;
int blockSize = AuMin(AuUInt(kFileCopyBlock), length);
auto uBlockSize = AuMin(AuUInt(kFileCopyBlock), uLength);
if (!::WriteFile(this->handle_, reinterpret_cast<const char *>(parameters.ptr) + offset, blockSize, &written, NULL))
if (this->pHandle_->IsAsync())
{
SysPushErrorIO("WriteFileEx IO Error: 0x{:x}, {}", GetLastError(), this->path_);
return false;
OVERLAPPED overlapped {};
overlapped.hEvent = hEventHandle;
if (!::WriteFile(hHandle,
reinterpret_cast<const char *>(parameters.ptr) + uOffset,
uBlockSize,
NULL,
&overlapped) &&
::GetLastError() != ERROR_IO_PENDING)
{
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);
parameters.outVariable = uOffset;
return false;
}
::CloseHandle(hEventHandle);
}
else
{
if (!::WriteFile(hHandle, reinterpret_cast<const char *>(parameters.ptr) + uOffset, uBlockSize, &written, NULL))
{
SysPushErrorIO("WriteFile IO Error: 0x{:x}, {}", GetLastError(), this->pHandle_ ? this->pHandle_->GetPath() : "");
AuWin32CloseHandle(hEventHandle);
parameters.outVariable = uOffset;
return false;
}
}
if (!written)
{
SysPushErrorIO();
parameters.outVariable = offset;
parameters.outVariable = uOffset;
AuWin32CloseHandle(hEventHandle);
return true;
}
offset += written;
length -= written;
uOffset += written;
uLength -= written;
}
if (!offset)
AuWin32CloseHandle(hEventHandle);
if (!uOffset)
{
return false;
}
parameters.outVariable = offset;
parameters.outVariable = uOffset;
return true;
}
void WinFileStream::WriteEoS()
{
if (this->handle_ == INVALID_HANDLE_VALUE)
auto hHandle = this->GetHandle();
if (hHandle == INVALID_HANDLE_VALUE)
{
SysPushErrorUninitialized();
return;
}
SetEndOfFile(this->handle_);
SetEndOfFile(hHandle);
}
void WinFileStream::Close()
{
if ((this->handle_ != INVALID_HANDLE_VALUE) &&
auto hHandle = this->GetHandle();
if ((hHandle != INVALID_HANDLE_VALUE) &&
(this->bShouldDelete))
{
FILE_DISPOSITION_INFO rm {};
rm.DeleteFile = true;
if (!(pSetFileInformationByHandle && pSetFileInformationByHandle(this->handle_, _FILE_INFO_BY_HANDLE_CLASS::FileDispositionInfo, &rm, sizeof(rm))))
if (!(pSetFileInformationByHandle &&
pSetFileInformationByHandle(hHandle, _FILE_INFO_BY_HANDLE_CLASS::FileDispositionInfo, &rm, sizeof(rm))))
{
SysPushErrorIO("Couldn't delete temporary file {}", this->path_);
SysPushErrorIO("Couldn't delete temporary file {}", this->pHandle_ ? this->pHandle_->GetPath() : "");
}
}
AuWin32CloseHandle(this->handle_);
AuResetMember(this->pHandle_);
}
void WinFileStream::Flush()
{
FlushFileBuffers(this->handle_);
auto hHandle = this->GetHandle();
::FlushFileBuffers(hHandle);
}
void WinFileStream::MakeTemporary()
@ -208,104 +319,57 @@ namespace Aurora::IO::FS
HANDLE WinFileStream::GetHandle()
{
return this->handle_;
return this->pHandle_ ?
(HANDLE)this->pHandle_->GetOSWriteHandleSafe().ValueOr(this->pHandle_->GetOSReadHandleSafe().ValueOr((AuUInt)INVALID_HANDLE_VALUE)) :
INVALID_HANDLE_VALUE;
}
static IFileStream *OpenNewEx(const AuString &path, EFileOpenMode openMode, EFileAdvisoryLockLevel lock, bool bCheck)
AUKN_SYM AuSPtr<IFileStream> OpenBlockingFileStreamFromHandle(AuSPtr<IIOHandle> pIOHandle)
{
auto pStream = AuMakeShared<WinFileStream>();
if (!pStream)
{
return nullptr;
}
pStream->Init(pIOHandle);
return pStream;
}
static IFileStream *OpenNewEx(const AuString &path,
EFileOpenMode openMode,
EFileAdvisoryLockLevel lock,
bool bCheck)
{
try
{
auto pathex = NormalizePathRet(path);
if (pathex.empty())
auto pHandle = AuIO::IOHandleShared();
if (!pHandle)
{
SysPushErrorMemory();
return nullptr;
}
AuIO::IIOHandle::HandleCreate createhandle(path);
createhandle.eAdvisoryLevel = lock;
createhandle.eMode = openMode;
createhandle.bFailIfNonEmptyFile = bCheck;
createhandle.bDirectIOMode = false;
createhandle.bAsyncHandle = false;
if (!pHandle->InitFromPath(createhandle))
{
return nullptr;
}
auto win32Path = Locale::ConvertFromUTF8(pathex);
if (win32Path.empty())
auto pStream = _new WinFileStream();
if (!pStream)
{
return nullptr;
}
HANDLE fileHandle;
fileHandle = INVALID_HANDLE_VALUE;
auto dwShare = NtLockAdvisoryToShare(lock);
switch (openMode)
{
case EFileOpenMode::eRead:
{
fileHandle = CreateFileW(win32Path.c_str(), GENERIC_READ, dwShare, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
break;
}
case EFileOpenMode::eReadWrite:
{
CreateDirectories(pathex, true);
if (bCheck)
{
fileHandle = ::CreateFileW(win32Path.c_str(),
GENERIC_WRITE | GENERIC_READ | DELETE,
NULL,
NULL,
CREATE_NEW,
FILE_ATTRIBUTE_NORMAL,
NULL);
}
else
{
fileHandle = CreateFileW(win32Path.c_str(), GENERIC_WRITE | GENERIC_READ | DELETE, dwShare, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (fileHandle == INVALID_HANDLE_VALUE)
{
fileHandle = CreateFileW(win32Path.c_str(), GENERIC_WRITE | GENERIC_READ | DELETE, dwShare, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
}
}
break;
}
case EFileOpenMode::eWrite:
{
CreateDirectories(pathex, true);
if (bCheck)
{
fileHandle = ::CreateFileW(win32Path.c_str(),
GENERIC_WRITE | DELETE,
NULL,
NULL,
CREATE_NEW,
FILE_ATTRIBUTE_NORMAL,
NULL);
}
else
{
fileHandle = CreateFileW(win32Path.c_str(), GENERIC_WRITE | FILE_READ_ATTRIBUTES | DELETE, dwShare, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (fileHandle == INVALID_HANDLE_VALUE)
{
fileHandle = CreateFileW(win32Path.c_str(), GENERIC_WRITE | DELETE, dwShare, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
}
}
break;
}
}
if (fileHandle == INVALID_HANDLE_VALUE)
{
SysPushErrorIO("Invalid filepath, couldn't open: {}", path);
return nullptr;
}
auto stream = _new WinFileStream();
if (!stream)
{
CloseHandle(fileHandle);
return nullptr;
}
stream->Init(fileHandle, pathex);
return stream;
pStream->Init(pHandle);
return pStream;
}
catch (...)
{

View File

@ -15,7 +15,7 @@ namespace Aurora::IO::FS
{
~WinFileStream();
void Init(HANDLE handle, const AuString &path);
void Init(AuSPtr<IIOHandle> pHandle);
AuUInt64 GetOffset() override;
bool SetOffset(AuUInt64 offset) override;
@ -28,11 +28,11 @@ namespace Aurora::IO::FS
void MakeTemporary() override;
HANDLE GetHandle();
private:
private:
AuSPtr<IIOHandle> pHandle_;
bool bShouldDelete {};
HANDLE handle_ = INVALID_HANDLE_VALUE;
AuString path_;
HANDLE hEventHandle_ { INVALID_HANDLE_VALUE };
};
}
#endif

View File

@ -88,12 +88,15 @@ namespace Aurora::IO::IPC
if (serverHandle != INVALID_HANDLE_VALUE)
{
this->hasClient_ = Loop::NewLSEvent(false, false, true);
SysAssert(this->hasClient_);
}
this->fsHandle_ = AuMakeShared<IO::FS::FileHandle>();
this->fsStream_ = AuMakeShared<IO::FS::NtAsyncFileStream>();
this->fsHandle_ = AuIO::IOHandleShared();
SysAssert(this->fsHandle_);
this->fsHandle_->Init(this->GetPipeHandle(), this->GetPipeHandle());
this->fsStream_ = AuMakeSharedPanic<IO::FS::NtAsyncFileStream>();
this->fsHandle_->InitFromMove((AuUInt)this->GetPipeHandle());
this->fsStream_->Init(this->fsHandle_);
TryConnect();

View File

@ -49,7 +49,7 @@ namespace Aurora::IO::IPC
private:
HANDLE serverHandle_ {INVALID_HANDLE_VALUE};
IPCHandle ipcHandle_;
AuSPtr<IO::FS::FileHandle> fsHandle_;
AuSPtr<IO::IIOHandle> fsHandle_;
AuSPtr<IO::FS::NtAsyncFileStream> fsStream_;
AuSPtr<IPCHasConnectionEvent> lshasConnection_;
bool bFirstTime {true};

View File

@ -14,6 +14,8 @@
#include "AuNetSocketServer.hpp"
#include "AuNetInterface.hpp"
#include "../AuIOHandle.hpp"
#if defined(AURORA_IS_MODERNNT_DERIVED)
#include "AuNetStream.NT.hpp"
#endif
@ -40,7 +42,7 @@ namespace Aurora::IO::Net
{
this->pWorker_->AddSocket(this);
this->osHandleOwner_ = AuMakeShared<AuFS::FileHandle>();
this->osHandleOwner_ = AuIO::IOHandleShared();
if (!this->osHandle_)
{
return;
@ -48,10 +50,11 @@ namespace Aurora::IO::Net
#if defined(AURORA_IS_MODERNNT_DERIVED)
//this->osHandleOwner_->Init((HANDLE)this->osHandle_, (HANDLE)this->osHandle_);
//this->osHandleOwner_->InitFromPairMove((HANDLE)this->osHandle_, (HANDLE)this->osHandle_);
#else
this->osHandleOwner_->Init((int)this->osHandle_, (int)this->osHandle_);
this->osHandleOwner_->InitFromPairMove((int)this->osHandle_, (int)this->osHandle_);
#endif
}
SocketBase::SocketBase(struct NetInterface *pInterface,
@ -65,7 +68,7 @@ namespace Aurora::IO::Net
pSocketDriver_(pSocketDriver),
remoteEndpoint_(endpoint)
{
this->osHandleOwner_ = AuMakeShared<AuFS::FileHandle>();
this->osHandleOwner_ = AuIO::IOHandleShared();
if (!this->osHandle_)
{
return;
@ -102,7 +105,8 @@ namespace Aurora::IO::Net
this->connectMany_.protocol = eProtocol;
}
this->osHandleOwner_ = AuMakeShared<AuFS::FileHandle>();
this->osHandleOwner_ = AuIO::IOHandleShared();
if (!this->osHandle_)
{
return;
@ -126,7 +130,8 @@ namespace Aurora::IO::Net
{
this->connectMany_.pDriver.reset();
this->osHandleOwner_ = AuMakeShared<AuFS::FileHandle>();
this->osHandleOwner_ = AuIO::IOHandleShared();
if (!this->osHandle_)
{
return;
@ -490,7 +495,7 @@ namespace Aurora::IO::Net
{
if (this->osHandleOwner_)
{
this->osHandleOwner_->bWriteLock = true;
AuStaticCast<AFileHandle>(this->osHandleOwner_)->uOSWriteHandle.Reset();
}
}

View File

@ -137,7 +137,7 @@ namespace Aurora::IO::Net
NetInterface *pInterface_;
SocketChannel socketChannel_;
AuSPtr<ISocketDriver> pSocketDriver_;
AuSPtr<FS::FileHandle> osHandleOwner_;
AuSPtr<IIOHandle> osHandleOwner_;
NetError error_;

View File

@ -243,8 +243,6 @@ namespace Aurora::IO::Net
auto er = WSAGetLastError();
if (bReturnValue)
{
::SetEvent(this->GetAlertable());
this->DispatchCb(this->dwLastAbstractStat);
return true;
}
else if (er == ERROR_IO_PENDING)
@ -276,6 +274,7 @@ namespace Aurora::IO::Net
}
this->pMemoryHold.reset();
this->pPin.reset();
return true;
}
else

View File

@ -371,7 +371,7 @@ namespace Aurora::Processes
if (this->startup_.fwdIn == EStreamForward::eAsyncPipe || this->startup_.fwdOut == EStreamForward::eAsyncPipe)
{
this->fsHandle_ = AuMakeShared<IO::FS::FileHandle>();
this->fsHandle_ = AuIO::IOHandleShared();
if (!this->fsHandle_)
{
return false;
@ -383,13 +383,13 @@ namespace Aurora::Processes
return false;
}
this->fsHandle_->Init(this->pipeStdOutRead_, this->pipeStdInWrite_);
this->fsHandle_->InitFromPairMove((AuUInt64)this->pipeStdOutRead_, (AuUInt64)this->pipeStdInWrite_);
this->fsStream_->Init(this->fsHandle_);
}
if (this->startup_.fwdErr == EStreamForward::eAsyncPipe)
{
this->fsErrorHandle_ = AuMakeShared<IO::FS::FileHandle>();
this->fsErrorHandle_ = AuIO::IOHandleShared();
if (!this->fsErrorHandle_)
{
return false;
@ -401,7 +401,7 @@ namespace Aurora::Processes
return false;
}
this->fsErrorHandle_->Init(this->pipeStdErrRead_, INVALID_HANDLE_VALUE);
this->fsErrorHandle_->InitFromPairMove((AuUInt64)this->pipeStdErrRead_, {});
this->fsErrorStream_->Init(this->fsErrorHandle_);
}

View File

@ -59,10 +59,10 @@ namespace Aurora::Processes
AuSPtr<AuLoop::ILoopSource> loopSource_;
AuSPtr<IO::FS::FileHandle> fsHandle_;
AuSPtr<IO::IIOHandle> fsHandle_;
AuSPtr<IO::FS::NtAsyncFileStream> fsStream_;
AuSPtr<IO::FS::FileHandle> fsErrorHandle_;
AuSPtr<IO::IIOHandle> fsErrorHandle_;
AuSPtr<IO::FS::NtAsyncFileStream> fsErrorStream_;
StartupParmaters startup_;