diff --git a/Include/Aurora/IO/FS/Async.hpp b/Include/Aurora/IO/FS/Async.hpp index c7568c2d..003a3589 100644 --- a/Include/Aurora/IO/FS/Async.hpp +++ b/Include/Aurora/IO/FS/Async.hpp @@ -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 OpenDirectIOAsyncFileStreamFromHandle(AuSPtr pIOHandle); + + AUKN_SYM AuSPtr OpenBufferedAsyncFileStreamFromHandle(AuSPtr pIOHandle); +#endif } \ No newline at end of file diff --git a/Include/Aurora/IO/FS/FileStream.hpp b/Include/Aurora/IO/FS/FileStream.hpp index f65c2999..4a8e17de 100644 --- a/Include/Aurora/IO/FS/FileStream.hpp +++ b/Include/Aurora/IO/FS/FileStream.hpp @@ -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 OpenBlockingFileStreamFromHandle(AuSPtr pIOHandle); } \ No newline at end of file diff --git a/Include/Aurora/IO/IO.hpp b/Include/Aurora/IO/IO.hpp index 24fe8274..cf93fb7d 100644 --- a/Include/Aurora/IO/IO.hpp +++ b/Include/Aurora/IO/IO.hpp @@ -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" diff --git a/Include/Aurora/IO/IOHandle.hpp b/Include/Aurora/IO/IOHandle.hpp new file mode 100644 index 00000000..b88f67d1 --- /dev/null +++ b/Include/Aurora/IO/IOHandle.hpp @@ -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 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 uOSReadHandle, + AuOptionalEx uOSWriteHandle) = 0; + + virtual AuUInt64 GetOSHandle() = 0; + + virtual AuUInt64 GetOSReadHandle() = 0; + + virtual AuOptionalEx GetOSReadHandleSafe() = 0; + + virtual AuUInt64 GetOSWriteHandle() = 0; + + virtual AuOptionalEx GetOSWriteHandleSafe() = 0; + + virtual bool IsValid() = 0; + + virtual bool HasUniqueWriteHandle() = 0; + + virtual bool IsAsync() = 0; + + virtual AuString GetPath() = 0; + }; + + AUKN_SHARED_SOO(IOHandle, IIOHandle, 256); +} \ No newline at end of file diff --git a/Include/Aurora/Memory/ByteBuffer.hpp b/Include/Aurora/Memory/ByteBuffer.hpp index 41cc025b..4b0a22d1 100644 --- a/Include/Aurora/Memory/ByteBuffer.hpp +++ b/Include/Aurora/Memory/ByteBuffer.hpp @@ -124,7 +124,7 @@ namespace Aurora::Memory { if (buffer.length) { - this->base = FAlloc(buffer.length); + this->base = ZAlloc(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(length) : nullptr; + this->base = length ? ZAlloc(length) : nullptr; if (!this->base) { Reset(); @@ -181,7 +181,7 @@ namespace Aurora::Memory inline ByteBuffer(const AuList &vector, bool circular = false, bool expandable = false) : flagCircular(circular), flagExpandable(expandable), flagReadError(0), flagWriteError(0) { this->scaleSize = kBufferInitialPower; - this->base = vector.size() ? FAlloc(vector.size()) : nullptr; + this->base = vector.size() ? ZAlloc(vector.size()) : nullptr; if (!this->base) { Reset(); diff --git a/Include/Aurora/Memory/ByteBuffer_Memory.inl b/Include/Aurora/Memory/ByteBuffer_Memory.inl index df1dc0dc..11a9814b 100644 --- a/Include/Aurora/Memory/ByteBuffer_Memory.inl +++ b/Include/Aurora/Memory/ByteBuffer_Memory.inl @@ -31,7 +31,7 @@ namespace Aurora::Memory return true; } - this->base = fast ? FAlloc(length) : ZAlloc(length); + this->base = ZAlloc(length); if (!this->base) { return false; @@ -65,7 +65,7 @@ namespace Aurora::Memory return true; } - this->base = fast ? FAlloc(length, alignment) : ZAlloc(length, alignment); + this->base = ZAlloc(length, alignment); if (!this->base) { return false; diff --git a/Source/IO/AuIOHandle.NT.cpp b/Source/IO/AuIOHandle.NT.cpp new file mode 100644 index 00000000..3361f158 --- /dev/null +++ b/Source/IO/AuIOHandle.NT.cpp @@ -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 +#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(pIOHandle); + } + + AUROXTL_INTERFACE_SOO_SRC_EX(AURORA_SYMBOL_EXPORT, IOHandle, NTIOHandle) +} \ No newline at end of file diff --git a/Source/IO/AuIOHandle.NT.hpp b/Source/IO/AuIOHandle.NT.hpp new file mode 100644 index 00000000..bcad3d45 --- /dev/null +++ b/Source/IO/AuIOHandle.NT.hpp @@ -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 +{ + +} \ No newline at end of file diff --git a/Source/IO/AuIOHandle.cpp b/Source/IO/AuIOHandle.cpp new file mode 100644 index 00000000..d210d008 --- /dev/null +++ b/Source/IO/AuIOHandle.cpp @@ -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 +#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 pHandle) + { + auto pSrc = AuStaticCast(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 uOSReadHandle, + AuOptionalEx 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 AFileHandle::GetOSReadHandleSafe() + { + return this->uOSReadHandle; + } + + AuUInt64 AFileHandle::GetOSWriteHandle() + { + return this->uOSWriteHandle.Value(); + } + + AuOptionalEx 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; + } +} \ No newline at end of file diff --git a/Source/IO/AuIOHandle.hpp b/Source/IO/AuIOHandle.hpp new file mode 100644 index 00000000..27d978b6 --- /dev/null +++ b/Source/IO/AuIOHandle.hpp @@ -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 pHandle) override; + + bool InitFromCopy(AuUInt64 uOSHandle) override; + + bool InitFromMove(AuUInt64 uOSHandle) override; + + bool InitFromPair(AuUInt64 uOSReadHandle, + AuUInt64 uOSWriteHandle) override; + + bool InitFromPairMove(AuOptionalEx uOSReadHandle, + AuOptionalEx uOSWriteHandle) override; + + AuUInt64 GetOSHandle() override; + + AuUInt64 GetOSReadHandle() override; + + AuOptionalEx GetOSReadHandleSafe() override; + + AuUInt64 GetOSWriteHandle() override; + + AuOptionalEx GetOSWriteHandleSafe() override; + + bool IsValid() override; + + bool HasUniqueWriteHandle() override; + + bool IsAsync() override; + + AuString GetPath() override; + + AuOptionalEx uOSWriteHandle; + AuOptionalEx uOSReadHandle; + AuSPtr 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); + }; +} \ No newline at end of file diff --git a/Source/IO/FS/Async.NT.cpp b/Source/IO/FS/Async.NT.cpp index 9612983c..4e23d69d 100644 --- a/Source/IO/FS/Async.NT.cpp +++ b/Source/IO/FS/Async.NT.cpp @@ -62,105 +62,14 @@ namespace Aurora::IO::FS AuWin32CloseHandle(this->event); } - FileHandle::~FileHandle() + AuSPtr 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 &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 NtAsyncFileStream::GetHandle() - { - return handle_; - } - - void NtAsyncFileStream::Init(const AuSPtr &handle) - { - this->handle_ = handle; + this->pHandle_ = pHandle; } AuSPtr 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 ¶meters) @@ -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 &handle) + bool NtAsyncFileTransaction::InitWeak(const AuSPtr &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 &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(reinterpret_cast(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 NtAsyncFileTransaction::GetFileHandle() + AuSPtr NtAsyncFileTransaction::GetFileHandle() { - return this->pHandle_; + return this->pHandle_ ? this->pHandle_ : AuTryLockMemoryType(this->wpHandle_); } AuSPtr 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; - 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(); - 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) diff --git a/Source/IO/FS/Async.NT.hpp b/Source/IO/FS/Async.NT.hpp index fb51e077..b9a48389 100644 --- a/Source/IO/FS/Async.NT.hpp +++ b/Source/IO/FS/Async.NT.hpp @@ -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 NewTransaction() override; @@ -38,19 +22,20 @@ namespace Aurora::IO::FS bool BlockingRead(AuUInt64 offset, const Memory::MemoryViewStreamWrite ¶meters) override; bool BlockingWrite(AuUInt64 offset, const Memory::MemoryViewStreamRead ¶meters) override; - void Init(const AuSPtr &handle); + void Init(const AuSPtr &pHandle); - AuSPtr GetHandle(); + AuSPtr GetHandle(); private: - AuSPtr handle_; + AuSPtr pHandle_; }; struct NtAsyncFileTransaction : IAsyncTransaction, AuEnableSharedFromThis { ~NtAsyncFileTransaction(); - bool Init(const AuSPtr &handle); + bool Init(const AuSPtr &handle); + bool InitWeak(const AuSPtr &handle); void ResetAIO(); bool StartRead(AuUInt64 offset, const AuSPtr &memoryView) override; @@ -78,7 +63,7 @@ namespace Aurora::IO::FS void DispatchCb(AuUInt32 len); HANDLE GetHandle(); - AuSPtr GetFileHandle(); + AuSPtr GetFileHandle(); OVERLAPPED overlap {}; HANDLE event = INVALID_HANDLE_VALUE; @@ -94,7 +79,8 @@ namespace Aurora::IO::FS AuSPtr pMemoryHold; private: - AuSPtr pHandle_; + AuSPtr pHandle_; + AuWPtr wpHandle_; AuSPtr pSub_; }; } \ No newline at end of file diff --git a/Source/IO/FS/FileStream.NT.cpp b/Source/IO/FS/FileStream.NT.cpp index 5167eb58..1fdcda95 100644 --- a/Source/IO/FS/FileStream.NT.cpp +++ b/Source/IO/FS/FileStream.NT.cpp @@ -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 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 ¶meters) { - 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(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(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(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 ¶meters) { - 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(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(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(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 OpenBlockingFileStreamFromHandle(AuSPtr pIOHandle) + { + auto pStream = AuMakeShared(); + 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 (...) { diff --git a/Source/IO/FS/FileStream.NT.hpp b/Source/IO/FS/FileStream.NT.hpp index 9a99b0ae..f7c461bc 100644 --- a/Source/IO/FS/FileStream.NT.hpp +++ b/Source/IO/FS/FileStream.NT.hpp @@ -15,7 +15,7 @@ namespace Aurora::IO::FS { ~WinFileStream(); - void Init(HANDLE handle, const AuString &path); + void Init(AuSPtr 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 pHandle_; bool bShouldDelete {}; - HANDLE handle_ = INVALID_HANDLE_VALUE; - AuString path_; + HANDLE hEventHandle_ { INVALID_HANDLE_VALUE }; }; } #endif \ No newline at end of file diff --git a/Source/IO/IPC/AuIPCPipe.NT.cpp b/Source/IO/IPC/AuIPCPipe.NT.cpp index e625d8df..c400adcb 100644 --- a/Source/IO/IPC/AuIPCPipe.NT.cpp +++ b/Source/IO/IPC/AuIPCPipe.NT.cpp @@ -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(); - this->fsStream_ = AuMakeShared(); + this->fsHandle_ = AuIO::IOHandleShared(); + SysAssert(this->fsHandle_); - this->fsHandle_->Init(this->GetPipeHandle(), this->GetPipeHandle()); + this->fsStream_ = AuMakeSharedPanic(); + + this->fsHandle_->InitFromMove((AuUInt)this->GetPipeHandle()); this->fsStream_->Init(this->fsHandle_); TryConnect(); diff --git a/Source/IO/IPC/AuIPCPipe.NT.hpp b/Source/IO/IPC/AuIPCPipe.NT.hpp index a4df6b5e..2d951945 100644 --- a/Source/IO/IPC/AuIPCPipe.NT.hpp +++ b/Source/IO/IPC/AuIPCPipe.NT.hpp @@ -49,7 +49,7 @@ namespace Aurora::IO::IPC private: HANDLE serverHandle_ {INVALID_HANDLE_VALUE}; IPCHandle ipcHandle_; - AuSPtr fsHandle_; + AuSPtr fsHandle_; AuSPtr fsStream_; AuSPtr lshasConnection_; bool bFirstTime {true}; diff --git a/Source/IO/Net/AuNetSocket.cpp b/Source/IO/Net/AuNetSocket.cpp index eb3ebde0..307c0807 100644 --- a/Source/IO/Net/AuNetSocket.cpp +++ b/Source/IO/Net/AuNetSocket.cpp @@ -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(); + 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(); + this->osHandleOwner_ = AuIO::IOHandleShared(); if (!this->osHandle_) { return; @@ -102,7 +105,8 @@ namespace Aurora::IO::Net this->connectMany_.protocol = eProtocol; } - this->osHandleOwner_ = AuMakeShared(); + this->osHandleOwner_ = AuIO::IOHandleShared(); + if (!this->osHandle_) { return; @@ -126,7 +130,8 @@ namespace Aurora::IO::Net { this->connectMany_.pDriver.reset(); - this->osHandleOwner_ = AuMakeShared(); + this->osHandleOwner_ = AuIO::IOHandleShared(); + if (!this->osHandle_) { return; @@ -490,7 +495,7 @@ namespace Aurora::IO::Net { if (this->osHandleOwner_) { - this->osHandleOwner_->bWriteLock = true; + AuStaticCast(this->osHandleOwner_)->uOSWriteHandle.Reset(); } } diff --git a/Source/IO/Net/AuNetSocket.hpp b/Source/IO/Net/AuNetSocket.hpp index 926555a0..e6cd840d 100644 --- a/Source/IO/Net/AuNetSocket.hpp +++ b/Source/IO/Net/AuNetSocket.hpp @@ -137,7 +137,7 @@ namespace Aurora::IO::Net NetInterface *pInterface_; SocketChannel socketChannel_; AuSPtr pSocketDriver_; - AuSPtr osHandleOwner_; + AuSPtr osHandleOwner_; NetError error_; diff --git a/Source/IO/Net/AuNetStream.NT.cpp b/Source/IO/Net/AuNetStream.NT.cpp index b389fbaa..3998ab2d 100644 --- a/Source/IO/Net/AuNetStream.NT.cpp +++ b/Source/IO/Net/AuNetStream.NT.cpp @@ -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 diff --git a/Source/Processes/AuProcess.NT.cpp b/Source/Processes/AuProcess.NT.cpp index d193eecc..f4d9f9d3 100644 --- a/Source/Processes/AuProcess.NT.cpp +++ b/Source/Processes/AuProcess.NT.cpp @@ -371,7 +371,7 @@ namespace Aurora::Processes if (this->startup_.fwdIn == EStreamForward::eAsyncPipe || this->startup_.fwdOut == EStreamForward::eAsyncPipe) { - this->fsHandle_ = AuMakeShared(); + 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(); + 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_); } diff --git a/Source/Processes/AuProcess.NT.hpp b/Source/Processes/AuProcess.NT.hpp index e5084934..7abd65b3 100644 --- a/Source/Processes/AuProcess.NT.hpp +++ b/Source/Processes/AuProcess.NT.hpp @@ -59,10 +59,10 @@ namespace Aurora::Processes AuSPtr loopSource_; - AuSPtr fsHandle_; + AuSPtr fsHandle_; AuSPtr fsStream_; - AuSPtr fsErrorHandle_; + AuSPtr fsErrorHandle_; AuSPtr fsErrorStream_; StartupParmaters startup_;