Index: src/libchcore/IFilesystem.h =================================================================== diff -u -N -r3c248d4f6d0fdb1e487cc868b2f0b219eec37ef4 -r6b927672a652279a203f6465ead20ffb9fe6bde1 --- src/libchcore/IFilesystem.h (.../IFilesystem.h) (revision 3c248d4f6d0fdb1e487cc868b2f0b219eec37ef4) +++ src/libchcore/IFilesystem.h (.../IFilesystem.h) (revision 6b927672a652279a203f6465ead20ffb9fe6bde1) @@ -57,7 +57,7 @@ virtual void FastMove(const TSmartPath& pathSource, const TSmartPath& pathDestination) = 0; virtual IFilesystemFindPtr CreateFinderObject(const TSmartPath& pathDir, const TSmartPath& pathMask) = 0; - virtual IFilesystemFilePtr CreateFileObject(const TSmartPath& pathFile, bool bNoBuffering) = 0; + virtual IFilesystemFilePtr CreateFileObject(IFilesystemFile::EOpenMode eMode, const TSmartPath& pathFile, bool bNoBuffering) = 0; virtual EPathsRelation GetPathsRelation(const TSmartPath& pathFirst, const TSmartPath& pathSecond) = 0; Index: src/libchcore/IFilesystemFile.h =================================================================== diff -u -N -r41383599835bbab64d854eed179a7db21a59c6bf -r6b927672a652279a203f6465ead20ffb9fe6bde1 --- src/libchcore/IFilesystemFile.h (.../IFilesystemFile.h) (revision 41383599835bbab64d854eed179a7db21a59c6bf) +++ src/libchcore/IFilesystemFile.h (.../IFilesystemFile.h) (revision 6b927672a652279a203f6465ead20ffb9fe6bde1) @@ -21,22 +21,28 @@ #include "libchcore.h" #include "TPath.h" -#include "TOverlappedDataBuffer.h" #include "CommonDataTypes.h" namespace chcore { + class TOverlappedDataBuffer; class TFileInfo; class LIBCHCORE_API IFilesystemFile { public: + enum EOpenMode + { + eMode_Read, + eMode_Write + }; + + public: static const unsigned int MaxSectorSize = 4096; public: virtual ~IFilesystemFile(); - virtual void OpenExistingForReading() = 0; virtual void CreateNewForWriting() = 0; virtual void OpenExistingForWriting() = 0; @@ -47,8 +53,8 @@ virtual void FinalizeFile(TOverlappedDataBuffer& rBuffer) = 0; virtual bool IsOpen() const = 0; - virtual file_size_t GetFileSize() const = 0; - virtual void GetFileInfo(TFileInfo& tFileInfo) const = 0; + virtual file_size_t GetFileSize() = 0; + virtual void GetFileInfo(TFileInfo& tFileInfo) = 0; virtual void Close() = 0; Index: src/libchcore/TFilesystemFileFeedbackWrapper.cpp =================================================================== diff -u -N -r734408890246965d47e6bbf2c2978371269dd1fd -r6b927672a652279a203f6465ead20ffb9fe6bde1 --- src/libchcore/TFilesystemFileFeedbackWrapper.cpp (.../TFilesystemFileFeedbackWrapper.cpp) (revision 734408890246965d47e6bbf2c2978371269dd1fd) +++ src/libchcore/TFilesystemFileFeedbackWrapper.cpp (.../TFilesystemFileFeedbackWrapper.cpp) (revision 6b927672a652279a203f6465ead20ffb9fe6bde1) @@ -22,6 +22,7 @@ #include #include "TFileInfo.h" #include "TWorkerThreadController.h" +#include "TOverlappedDataBuffer.h" namespace chcore { @@ -42,73 +43,6 @@ throw TCoreException(eErr_InvalidArgument, L"spFilesystem is NULL", LOCATION); } - TSubTaskBase::ESubOperationResult TFilesystemFileFeedbackWrapper::OpenSourceFileFB() - { - bool bRetry = false; - - m_spFile->Close(); - - do - { - bRetry = false; - DWORD dwLastError = ERROR_SUCCESS; - - try - { - m_spFile->OpenExistingForReading(); - - return TSubTaskBase::eSubResult_Continue; - } - catch (const TFileException& e) - { - dwLastError = e.GetNativeError(); - } - - TFeedbackResult frResult = m_spFeedbackHandler->FileError(m_spFile->GetFilePath().ToWString(), TString(), EFileError::eCreateError, dwLastError); - switch (frResult.GetResult()) - { - case EFeedbackResult::eResult_Skip: - return TSubTaskBase::eSubResult_Continue; - - case EFeedbackResult::eResult_Cancel: - { - // log - TString strFormat = _T("Cancel request [error %errno] while opening source file %path (OpenSourceFileFB)"); - strFormat.Replace(_T("%errno"), boost::lexical_cast(dwLastError).c_str()); - strFormat.Replace(_T("%path"), m_spFile->GetFilePath().ToString()); - LOG_ERROR(m_spLog) << strFormat.c_str(); - - return TSubTaskBase::eSubResult_CancelRequest; - } - - case EFeedbackResult::eResult_Pause: - return TSubTaskBase::eSubResult_PauseRequest; - - case EFeedbackResult::eResult_Retry: - { - // log - TString strFormat = _T("Retrying [error %errno] to open source file %path (OpenSourceFileFB)"); - strFormat.Replace(_T("%errno"), boost::lexical_cast(dwLastError).c_str()); - strFormat.Replace(_T("%path"), m_spFile->GetFilePath().ToString()); - LOG_ERROR(m_spLog) << strFormat.c_str(); - - bRetry = true; - break; - } - - default: - BOOST_ASSERT(FALSE); // unknown result - throw TCoreException(eErr_UnhandledCase, L"Feedback result unknown", LOCATION); - } - - if(WasKillRequested(frResult)) - return TSubTaskBase::eSubResult_KillRequest; - } - while(bRetry); - - return TSubTaskBase::eSubResult_Continue; - } - TSubTaskBase::ESubOperationResult TFilesystemFileFeedbackWrapper::OpenExistingDestinationFileFB(bool bProtectReadOnlyFiles) { bool bRetry = false; Index: src/libchcore/TFilesystemFileFeedbackWrapper.h =================================================================== diff -u -N -r734408890246965d47e6bbf2c2978371269dd1fd -r6b927672a652279a203f6465ead20ffb9fe6bde1 --- src/libchcore/TFilesystemFileFeedbackWrapper.h (.../TFilesystemFileFeedbackWrapper.h) (revision 734408890246965d47e6bbf2c2978371269dd1fd) +++ src/libchcore/TFilesystemFileFeedbackWrapper.h (.../TFilesystemFileFeedbackWrapper.h) (revision 6b927672a652279a203f6465ead20ffb9fe6bde1) @@ -37,7 +37,6 @@ const IFilesystemPtr& spFilesystem); TFilesystemFileFeedbackWrapper& operator=(const TFilesystemFileFeedbackWrapper&) = delete; - TSubTaskBase::ESubOperationResult OpenSourceFileFB(); TSubTaskBase::ESubOperationResult OpenExistingDestinationFileFB(bool bProtectReadOnlyFiles); TSubTaskBase::ESubOperationResult OpenDestinationFileFB(const TFileInfoPtr& spSrcFileInfo, unsigned long long& ullSeekTo, bool& bFreshlyCreated, bool& bSkip, bool bProtectReadOnlyFiles); Index: src/libchcore/TLocalFilesystem.cpp =================================================================== diff -u -N -r3c248d4f6d0fdb1e487cc868b2f0b219eec37ef4 -r6b927672a652279a203f6465ead20ffb9fe6bde1 --- src/libchcore/TLocalFilesystem.cpp (.../TLocalFilesystem.cpp) (revision 3c248d4f6d0fdb1e487cc868b2f0b219eec37ef4) +++ src/libchcore/TLocalFilesystem.cpp (.../TLocalFilesystem.cpp) (revision 6b927672a652279a203f6465ead20ffb9fe6bde1) @@ -320,10 +320,10 @@ return std::shared_ptr(new TLocalFilesystemFind(pathDir, pathMask, m_spLog->GetLogFileData())); } - IFilesystemFilePtr TLocalFilesystem::CreateFileObject(const TSmartPath& pathFile, bool bNoBuffering) + IFilesystemFilePtr TLocalFilesystem::CreateFileObject(IFilesystemFile::EOpenMode eMode, const TSmartPath& pathFile, bool bNoBuffering) { LOG_TRACE(m_spLog) << L"Creating file object for path " << pathFile << L" with no-buffering set to " << bNoBuffering; - return std::shared_ptr(new TLocalFilesystemFile(pathFile, bNoBuffering, m_spLog->GetLogFileData())); + return std::shared_ptr(new TLocalFilesystemFile(eMode, pathFile, bNoBuffering, m_spLog->GetLogFileData())); } TSmartPath TLocalFilesystem::PrependPathExtensionIfNeeded(const TSmartPath& pathInput) Index: src/libchcore/TLocalFilesystem.h =================================================================== diff -u -N -r3c248d4f6d0fdb1e487cc868b2f0b219eec37ef4 -r6b927672a652279a203f6465ead20ffb9fe6bde1 --- src/libchcore/TLocalFilesystem.h (.../TLocalFilesystem.h) (revision 3c248d4f6d0fdb1e487cc868b2f0b219eec37ef4) +++ src/libchcore/TLocalFilesystem.h (.../TLocalFilesystem.h) (revision 6b927672a652279a203f6465ead20ffb9fe6bde1) @@ -58,7 +58,7 @@ virtual void FastMove(const TSmartPath& pathSource, const TSmartPath& pathDestination) override; virtual IFilesystemFindPtr CreateFinderObject(const TSmartPath& pathDir, const TSmartPath& pathMask) override; - virtual IFilesystemFilePtr CreateFileObject(const TSmartPath& pathFile, bool bNoBuffering) override; + virtual IFilesystemFilePtr CreateFileObject(IFilesystemFile::EOpenMode eMode, const TSmartPath& pathFile, bool bNoBuffering) override; virtual EPathsRelation GetPathsRelation(const TSmartPath& pathFirst, const TSmartPath& pathSecond) override; Index: src/libchcore/TLocalFilesystemFile.cpp =================================================================== diff -u -N -r1506d51ff1c0a5d156dab398051efc0c87473e81 -r6b927672a652279a203f6465ead20ffb9fe6bde1 --- src/libchcore/TLocalFilesystemFile.cpp (.../TLocalFilesystemFile.cpp) (revision 1506d51ff1c0a5d156dab398051efc0c87473e81) +++ src/libchcore/TLocalFilesystemFile.cpp (.../TLocalFilesystemFile.cpp) (revision 6b927672a652279a203f6465ead20ffb9fe6bde1) @@ -35,9 +35,10 @@ // compile-time check - ensure the buffer granularity used for transfers are bigger than expected sector size static_assert(TLocalFilesystemFile::MaxSectorSize <= TBufferSizes::BufferGranularity, "Buffer granularity must be equal to or bigger than the max sector size"); - TLocalFilesystemFile::TLocalFilesystemFile(const TSmartPath& pathFile, bool bNoBuffering, const logger::TLogFileDataPtr& spLogFileData) : + TLocalFilesystemFile::TLocalFilesystemFile(EOpenMode eMode, const TSmartPath& pathFile, bool bNoBuffering, const logger::TLogFileDataPtr& spLogFileData) : m_pathFile(TLocalFilesystem::PrependPathExtensionIfNeeded(pathFile)), m_hFile(INVALID_HANDLE_VALUE), + m_eMode(eMode), m_bNoBuffering(bNoBuffering), m_spLog(logger::MakeLogger(spLogFileData, L"Filesystem-File")) { @@ -61,10 +62,25 @@ return FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED | FILE_FLAG_SEQUENTIAL_SCAN | (bNoBuffering ? FILE_FLAG_NO_BUFFERING : 0); } - void TLocalFilesystemFile::OpenExistingForReading() + void TLocalFilesystemFile::EnsureOpen() { - Close(); + if(m_hFile != INVALID_HANDLE_VALUE) + return; + if(m_eMode == eMode_Read) + OpenExistingForReading(); + else + { + if(!IsOpen()) + { + LOG_ERROR(m_spLog) << L"File not open" << GetFileInfoForLog(m_bNoBuffering); + throw TFileException(eErr_FileNotOpen, ERROR_INVALID_HANDLE, m_pathFile, L"File not open yet. Cannot truncate.", LOCATION); + } + } + } + + void TLocalFilesystemFile::OpenExistingForReading() + { LOG_DEBUG(m_spLog) << L"Opening existing file for reading" << GetFileInfoForLog(m_bNoBuffering); m_hFile = ::CreateFile(m_pathFile.ToString(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, GetFlagsAndAttributes(m_bNoBuffering), nullptr); @@ -129,11 +145,7 @@ { LOG_TRACE(m_spLog) << "Truncating file to: " << fsNewSize << GetFileInfoForLog(m_bNoBuffering); - if (!IsOpen()) - { - LOG_ERROR(m_spLog) << L"Cannot truncate - file not open" << GetFileInfoForLog(m_bNoBuffering); - throw TFileException(eErr_FileNotOpen, ERROR_INVALID_HANDLE, m_pathFile, L"File not open yet. Cannot truncate.", LOCATION); - } + EnsureOpen(); // when no-buffering is used, there are cases where we'd need to switch to buffered ops // to adjust file size @@ -190,11 +202,7 @@ L"; buffer-order: " << rBuffer.GetFilePosition() << GetFileInfoForLog(m_bNoBuffering); - if (!IsOpen()) - { - LOG_ERROR(m_spLog) << L"Read request failed - file not open" << L"; buffer-order: " << rBuffer.GetFilePosition() << GetFileInfoForLog(m_bNoBuffering); - throw TFileException(eErr_FileNotOpen, ERROR_INVALID_HANDLE, m_pathFile, L"Cannot read from closed file", LOCATION); - } + EnsureOpen(); if (!::ReadFileEx(m_hFile, rBuffer.GetBufferPtr(), rBuffer.GetRequestedDataSize(), &rBuffer, OverlappedReadCompleted)) { @@ -238,11 +246,7 @@ L"; buffer-order: " << rBuffer.GetFilePosition() << GetFileInfoForLog(m_bNoBuffering); - if (!IsOpen()) - { - LOG_ERROR(m_spLog) << L"Write request failed - file not open" << L"; buffer-order: " << rBuffer.GetFilePosition() << GetFileInfoForLog(m_bNoBuffering); - throw TFileException(eErr_FileNotOpen, ERROR_INVALID_HANDLE, m_pathFile, L"Cannot write to closed file", LOCATION); - } + EnsureOpen(); DWORD dwToWrite = boost::numeric_cast(rBuffer.GetRealDataSize()); @@ -273,11 +277,7 @@ L"; buffer-order: " << rBuffer.GetFilePosition() << GetFileInfoForLog(m_bNoBuffering); - if (!IsOpen()) - { - LOG_ERROR(m_spLog) << L"Cannot finalize file - file not open" << L"; buffer-order: " << rBuffer.GetFilePosition() << GetFileInfoForLog(m_bNoBuffering); - throw TFileException(eErr_FileNotOpen, ERROR_INVALID_HANDLE, m_pathFile, L"Cannot write to closed file", LOCATION); - } + EnsureOpen(); if (m_bNoBuffering && rBuffer.IsLastPart()) { @@ -321,15 +321,11 @@ InternalClose(); } - file_size_t TLocalFilesystemFile::GetFileSize() const + file_size_t TLocalFilesystemFile::GetFileSize() { LOG_DEBUG(m_spLog) << L"Retrieving file size" << GetFileInfoForLog(m_bNoBuffering); - if (!IsOpen()) - { - LOG_ERROR(m_spLog) << L"Retrieving file size failed - file not open" << GetFileInfoForLog(m_bNoBuffering); - return 0; - } + EnsureOpen(); BY_HANDLE_FILE_INFORMATION bhfi; @@ -350,15 +346,11 @@ return uli.QuadPart; } - void TLocalFilesystemFile::GetFileInfo(TFileInfo& tFileInfo) const + void TLocalFilesystemFile::GetFileInfo(TFileInfo& tFileInfo) { LOG_DEBUG(m_spLog) << L"Retrieving file information" << GetFileInfoForLog(m_bNoBuffering); - if (!IsOpen()) - { - LOG_ERROR(m_spLog) << L"Retrieving file information failed - file not open" << GetFileInfoForLog(m_bNoBuffering); - throw TFileException(eErr_FileNotOpen, ERROR_INVALID_HANDLE, m_pathFile, L"File not open. Cannot get file info.", LOCATION); - } + EnsureOpen(); BY_HANDLE_FILE_INFORMATION bhfi; Index: src/libchcore/TLocalFilesystemFile.h =================================================================== diff -u -N -rf8fcbbd1d2321cf0c8be79526c449384af654e49 -r6b927672a652279a203f6465ead20ffb9fe6bde1 --- src/libchcore/TLocalFilesystemFile.h (.../TLocalFilesystemFile.h) (revision f8fcbbd1d2321cf0c8be79526c449384af654e49) +++ src/libchcore/TLocalFilesystemFile.h (.../TLocalFilesystemFile.h) (revision 6b927672a652279a203f6465ead20ffb9fe6bde1) @@ -34,7 +34,6 @@ public: virtual ~TLocalFilesystemFile(); - virtual void OpenExistingForReading() override; virtual void CreateNewForWriting() override; virtual void OpenExistingForWriting() override; @@ -45,17 +44,21 @@ virtual void FinalizeFile(TOverlappedDataBuffer& rBuffer) override; virtual bool IsOpen() const override { return m_hFile != INVALID_HANDLE_VALUE; } - virtual file_size_t GetFileSize() const override; - virtual void GetFileInfo(TFileInfo& tFileInfo) const override; + virtual file_size_t GetFileSize() override; + virtual void GetFileInfo(TFileInfo& tFileInfo) override; virtual TSmartPath GetFilePath() const override; virtual void Close() override; virtual file_size_t GetSeekPositionForResume(file_size_t fsLastAvailablePosition) override; private: - TLocalFilesystemFile(const TSmartPath& pathFile, bool bNoBuffering, const logger::TLogFileDataPtr& spLogFileData); + TLocalFilesystemFile(EOpenMode eMode, const TSmartPath& pathFile, bool bNoBuffering, const logger::TLogFileDataPtr& spLogFileData); + void EnsureOpen(); + + void OpenExistingForReading(); + DWORD GetFlagsAndAttributes(bool bNoBuffering) const; void OpenExistingForWriting(bool bNoBuffering); @@ -66,6 +69,7 @@ private: TSmartPath m_pathFile; HANDLE m_hFile; + EOpenMode m_eMode; bool m_bNoBuffering; #pragma warning(push) #pragma warning(disable: 4251) Index: src/libchcore/TSubTaskCopyMove.cpp =================================================================== diff -u -N -r980c1a0de537813728871676200a0960410b11fb -r6b927672a652279a203f6465ead20ffb9fe6bde1 --- src/libchcore/TSubTaskCopyMove.cpp (.../TSubTaskCopyMove.cpp) (revision 980c1a0de537813728871676200a0960410b11fb) +++ src/libchcore/TSubTaskCopyMove.cpp (.../TSubTaskCopyMove.cpp) (revision 6b927672a652279a203f6465ead20ffb9fe6bde1) @@ -38,7 +38,6 @@ #include "TScopedRunningTimeTracker.h" #include "TFeedbackHandlerWrapper.h" #include "TOverlappedMemoryPool.h" -#include "TOverlappedDataBuffer.h" #include "RoundingFunctions.h" #include "TTaskConfigBufferSizes.h" #include "TFileException.h" @@ -349,8 +348,8 @@ bool bNoBuffer = (GetTaskPropValue(rConfig) && pData->spSrcFile->GetLength64() >= GetTaskPropValue(rConfig)); - IFilesystemFilePtr fileSrc = spFilesystem->CreateFileObject(pData->spSrcFile->GetFullFilePath(), bNoBuffer); - IFilesystemFilePtr fileDst = spFilesystem->CreateFileObject(pData->pathDstFile, bNoBuffer); + IFilesystemFilePtr fileSrc = spFilesystem->CreateFileObject(IFilesystemFile::eMode_Read, pData->spSrcFile->GetFullFilePath(), bNoBuffer); + IFilesystemFilePtr fileDst = spFilesystem->CreateFileObject(IFilesystemFile::eMode_Write, pData->pathDstFile, bNoBuffer); TFilesystemFileFeedbackWrapperPtr spSrcFileWrapper(std::make_shared(fileSrc, spFeedbackHandler, GetContext().GetLogFileData(), rThreadController, spFilesystem)); TFilesystemFileFeedbackWrapperPtr spDstFileWrapper(std::make_shared(fileDst, spFeedbackHandler, GetContext().GetLogFileData(), rThreadController, spFilesystem)); @@ -402,19 +401,8 @@ unsigned long long ullProcessedSize = m_spSubTaskStats->GetCurrentItemProcessedSize(); // first open the source file and handle any failures - TSubTaskCopyMove::ESubOperationResult eResult = rSrcFile.OpenSourceFileFB(); - if(eResult != TSubTaskBase::eSubResult_Continue) - return eResult; - else if(!rSrcFile.IsOpen()) - { - // invalid handle = operation skipped by user - AdjustProcessedSizeForSkip(pData->spSrcFile); + TSubTaskCopyMove::ESubOperationResult eResult = eSubResult_Continue; - pData->bProcessed = false; - bSkip = true; - return TSubTaskBase::eSubResult_Continue; - } - // update the source file size (it might differ from the time this file was originally scanned). // NOTE: this kind of update could be also done when copying chunks of data beyond the original end-of-file, // but it would require frequent total size updates and thus - serializations).