Index: src/libchcore/IFeedbackHandler.h =================================================================== diff -u -r4d1f8110906889d56552771fb58a6de86bc54a29 -r89f857792bba8752de98ddd477949e45cef5ba5a --- src/libchcore/IFeedbackHandler.h (.../IFeedbackHandler.h) (revision 4d1f8110906889d56552771fb58a6de86bc54a29) +++ src/libchcore/IFeedbackHandler.h (.../IFeedbackHandler.h) (revision 89f857792bba8752de98ddd477949e45cef5ba5a) @@ -45,6 +45,9 @@ virtual TFeedbackResult OperationFinished() = 0; virtual TFeedbackResult OperationError() = 0; + // retry interval (in ms) + virtual DWORD GetRetryInterval() const = 0; + // reset permanent states virtual void RestoreDefaults() = 0; Index: src/libchcore/TFeedbackHandlerBase.cpp =================================================================== diff -u -r4d1f8110906889d56552771fb58a6de86bc54a29 -r89f857792bba8752de98ddd477949e45cef5ba5a --- src/libchcore/TFeedbackHandlerBase.cpp (.../TFeedbackHandlerBase.cpp) (revision 4d1f8110906889d56552771fb58a6de86bc54a29) +++ src/libchcore/TFeedbackHandlerBase.cpp (.../TFeedbackHandlerBase.cpp) (revision 89f857792bba8752de98ddd477949e45cef5ba5a) @@ -107,6 +107,11 @@ } } + DWORD TFeedbackHandlerBase::GetRetryInterval() const + { + return 100; + } + void TFeedbackHandlerBase::RestoreDefaults() { m_eFileError = EFeedbackResult::eResult_Unknown; @@ -115,30 +120,4 @@ m_eOperationFinished = EFeedbackResult::eResult_Unknown; m_eOperationError = EFeedbackResult::eResult_Unknown; } -/* - - TFeedbackResult TFeedbackHandlerBase::FileError(const TString& / *strSrcPath* /, const TString& / *strDstPath* /, EFileError / *eFileError* /, unsigned long / *ulError* /) - { - return TFeedbackResult(m_eFileError, HasFileErrorPermanentResponse()); - } - - TFeedbackResult TFeedbackHandlerBase::FileAlreadyExists(const TFileInfo& / *rSrcFileInfo* /, const TFileInfo& / *rDstFileInfo* /) - { - return m_eFileAlreadyExists; - } - - TFeedbackResult TFeedbackHandlerBase::NotEnoughSpace(const TString& / *strSrcPath* /, const TString& / *strDstPath* /, unsigned long long / *ullRequiredSize* /) - { - return m_eNotEnoughSpace; - } - - TFeedbackResult TFeedbackHandlerBase::OperationFinished() - { - return m_eOperationFinished; - } - - TFeedbackResult TFeedbackHandlerBase::OperationError() - { - return m_eOperationError; - }*/ } Index: src/libchcore/TFeedbackHandlerBase.h =================================================================== diff -u -r4d1f8110906889d56552771fb58a6de86bc54a29 -r89f857792bba8752de98ddd477949e45cef5ba5a --- src/libchcore/TFeedbackHandlerBase.h (.../TFeedbackHandlerBase.h) (revision 4d1f8110906889d56552771fb58a6de86bc54a29) +++ src/libchcore/TFeedbackHandlerBase.h (.../TFeedbackHandlerBase.h) (revision 89f857792bba8752de98ddd477949e45cef5ba5a) @@ -35,15 +35,6 @@ TFeedbackHandlerBase(); virtual ~TFeedbackHandlerBase(); -/* - virtual TFeedbackResult FileError(const TString& strSrcPath, const TString& strDstPath, EFileError eFileError, unsigned long ulError) override; - virtual TFeedbackResult FileAlreadyExists(const TFileInfo& spSrcFileInfo, const TFileInfo& spDstFileInfo) override; - virtual TFeedbackResult NotEnoughSpace(const TString& strSrcPath, const TString& strDstPath, unsigned long long ullRequiredSize) override; - - virtual TFeedbackResult OperationFinished() override; - virtual TFeedbackResult OperationError() override; -*/ - // marking responses as permanent void SetFileErrorPermanentResponse(EFeedbackResult ePermanentResult) { m_eFileError = ePermanentResult; } EFeedbackResult GetFileErrorPermanentResponse() const { return m_eFileError; } @@ -65,6 +56,8 @@ static void InitColumns(const ISerializerContainerPtr& spContainer); void Load(const ISerializerContainerPtr& spContainer); + virtual DWORD GetRetryInterval() const override; + private: enum EModifications { Index: src/libchcore/TFeedbackHandlerWrapper.cpp =================================================================== diff -u -r4d1f8110906889d56552771fb58a6de86bc54a29 -r89f857792bba8752de98ddd477949e45cef5ba5a --- src/libchcore/TFeedbackHandlerWrapper.cpp (.../TFeedbackHandlerWrapper.cpp) (revision 4d1f8110906889d56552771fb58a6de86bc54a29) +++ src/libchcore/TFeedbackHandlerWrapper.cpp (.../TFeedbackHandlerWrapper.cpp) (revision 89f857792bba8752de98ddd477949e45cef5ba5a) @@ -81,4 +81,10 @@ { return m_spFeedbackHandler->Load(spContainer); } + + DWORD TFeedbackHandlerWrapper::GetRetryInterval() const + { + return m_spFeedbackHandler->GetRetryInterval(); + } + } Index: src/libchcore/TFeedbackHandlerWrapper.h =================================================================== diff -u -r4d1f8110906889d56552771fb58a6de86bc54a29 -r89f857792bba8752de98ddd477949e45cef5ba5a --- src/libchcore/TFeedbackHandlerWrapper.h (.../TFeedbackHandlerWrapper.h) (revision 4d1f8110906889d56552771fb58a6de86bc54a29) +++ src/libchcore/TFeedbackHandlerWrapper.h (.../TFeedbackHandlerWrapper.h) (revision 89f857792bba8752de98ddd477949e45cef5ba5a) @@ -47,6 +47,8 @@ virtual void Store(const ISerializerContainerPtr& spContainer) const override; virtual void Load(const ISerializerContainerPtr& spContainer) override; + virtual DWORD GetRetryInterval() const override; + private: IFeedbackHandlerPtr m_spFeedbackHandler; TScopedRunningTimeTracker& m_rTimeGuard; Index: src/libchcore/TFilesystemFeedbackWrapper.cpp =================================================================== diff -u -r4d1f8110906889d56552771fb58a6de86bc54a29 -r89f857792bba8752de98ddd477949e45cef5ba5a --- src/libchcore/TFilesystemFeedbackWrapper.cpp (.../TFilesystemFeedbackWrapper.cpp) (revision 4d1f8110906889d56552771fb58a6de86bc54a29) +++ src/libchcore/TFilesystemFeedbackWrapper.cpp (.../TFilesystemFeedbackWrapper.cpp) (revision 89f857792bba8752de98ddd477949e45cef5ba5a) @@ -21,13 +21,15 @@ #include #include "TFileException.h" #include "TFileInfo.h" +#include "TWorkerThreadController.h" namespace chcore { - TFilesystemFeedbackWrapper::TFilesystemFeedbackWrapper(const IFeedbackHandlerPtr& spFeedbackHandler, const IFilesystemPtr& spFilesystem, icpf::log_file& rLog) : + TFilesystemFeedbackWrapper::TFilesystemFeedbackWrapper(const IFeedbackHandlerPtr& spFeedbackHandler, const IFilesystemPtr& spFilesystem, icpf::log_file& rLog, TWorkerThreadController& rThreadController) : m_spFeedbackHandler(spFeedbackHandler), m_spFilesystem(spFilesystem), - m_rLog(rLog) + m_rLog(rLog), + m_rThreadController(rThreadController) { if (!spFilesystem) THROW_CORE_EXCEPTION_MSG(eErr_InvalidArgument, L"Filesystem not provided"); @@ -75,21 +77,32 @@ return TSubTaskBase::eSubResult_PauseRequest; case EFeedbackResult::eResult_Skip: - break; // just do nothing + return TSubTaskBase::eSubResult_Continue; default: BOOST_ASSERT(FALSE); // unknown result THROW_CORE_EXCEPTION(eErr_UnhandledCase); } + + if(WasKillRequested(frResult)) + return TSubTaskBase::eSubResult_KillRequest; } while (bRetry); return TSubTaskBase::eSubResult_Continue; } + bool TFilesystemFeedbackWrapper::WasKillRequested(const TFeedbackResult& rFeedbackResult) const + { + if(m_rThreadController.KillRequested(rFeedbackResult.IsAutomatedReply() ? m_spFeedbackHandler->GetRetryInterval() : 0)) + return true; + return false; + } + TSubTaskBase::ESubOperationResult TFilesystemFeedbackWrapper::CheckForFreeSpaceFB(const TSmartPath& pathFirstSrc, const TSmartPath& pathDestination, unsigned long long ullNeededSize) { unsigned long long ullAvailableSize = 0; + TFeedbackResult frResult(eResult_Unknown, false); bool bRetry = false; do @@ -119,15 +132,15 @@ strFormat.Replace(_T("%path"), pathDestination.ToString()); m_rLog.loge(strFormat.c_str()); - TFeedbackResult frResult = m_spFeedbackHandler->FileError(pathDestination.ToWString(), TString(), EFileError::eCheckForFreeSpace, dwLastError); + frResult = m_spFeedbackHandler->FileError(pathDestination.ToWString(), TString(), EFileError::eCheckForFreeSpace, dwLastError); switch (frResult.GetResult()) { case EFeedbackResult::eResult_Cancel: return TSubTaskBase::eSubResult_CancelRequest; case EFeedbackResult::eResult_Retry: bRetry = true; - continue; + break; case EFeedbackResult::eResult_Pause: return TSubTaskBase::eSubResult_PauseRequest; @@ -141,14 +154,14 @@ } } - if (ullNeededSize > ullAvailableSize) + if (!bRetry && ullNeededSize > ullAvailableSize) { TString strFormat = _T("Not enough free space on disk - needed %needsize bytes for data, available: %availablesize bytes."); strFormat.Replace(_t("%needsize"), boost::lexical_cast(ullNeededSize).c_str()); strFormat.Replace(_t("%availablesize"), boost::lexical_cast(ullAvailableSize).c_str()); m_rLog.logw(strFormat.c_str()); - TFeedbackResult frResult = m_spFeedbackHandler->NotEnoughSpace(pathFirstSrc.ToWString(), pathDestination.ToWString(), ullNeededSize); + frResult = m_spFeedbackHandler->NotEnoughSpace(pathFirstSrc.ToWString(), pathDestination.ToWString(), ullNeededSize); switch (frResult.GetResult()) { case EFeedbackResult::eResult_Cancel: @@ -169,8 +182,12 @@ THROW_CORE_EXCEPTION(eErr_UnhandledCase); } } - } while (bRetry); + if(bRetry && WasKillRequested(frResult)) + return TSubTaskBase::eSubResult_KillRequest; + } + while (bRetry); + return TSubTaskBase::eSubResult_Continue; } @@ -221,20 +238,24 @@ case EFeedbackResult::eResult_Retry: bRetry = true; - continue; // no fcIndex bump, since we are trying again + break; // no fcIndex bump, since we are trying again case EFeedbackResult::eResult_Pause: return TSubTaskBase::eSubResult_PauseRequest; case EFeedbackResult::eResult_Skip: - break; // just do nothing + TSubTaskBase::eSubResult_Continue; // just do nothing default: BOOST_ASSERT(FALSE); // unknown result THROW_CORE_EXCEPTION(eErr_UnhandledCase); } - } while (bRetry); + if(WasKillRequested(frResult)) + return TSubTaskBase::eSubResult_KillRequest; + } + while (bRetry); + return TSubTaskBase::eSubResult_Continue; } @@ -285,20 +306,24 @@ case EFeedbackResult::eResult_Retry: bRetry = true; - continue; // no fcIndex bump, since we are trying again + break; case EFeedbackResult::eResult_Pause: return TSubTaskBase::eSubResult_PauseRequest; case EFeedbackResult::eResult_Skip: - break; // just do nothing + return TSubTaskBase::eSubResult_Continue; // just do nothing default: BOOST_ASSERT(FALSE); // unknown result THROW_CORE_EXCEPTION(eErr_UnhandledCase); } - } while (bRetry); + if(WasKillRequested(frResult)) + return TSubTaskBase::eSubResult_KillRequest; + } + while(bRetry); + return TSubTaskBase::eSubResult_Continue; } @@ -327,41 +352,43 @@ if (dwLastError == ERROR_ACCESS_DENIED || dwLastError == ERROR_ALREADY_EXISTS || dwLastError == ERROR_NOT_SAME_DEVICE) { bSkip = true; - break; + return TSubTaskBase::eSubResult_Continue; } - else - { - //log - TString strFormat = _T("Error %errno while calling fast move %srcpath -> %dstpath (TSubTaskFastMove)"); - strFormat.Replace(_T("%errno"), boost::lexical_cast(dwLastError).c_str()); - strFormat.Replace(_T("%srcpath"), spFileInfo->GetFullFilePath().ToString()); - strFormat.Replace(_T("%dstpath"), pathDestination.ToString()); - m_rLog.loge(strFormat.c_str()); - TFeedbackResult frResult = m_spFeedbackHandler->FileError(pathSrc.ToWString(), pathDestination.ToWString(), EFileError::eFastMoveError, dwLastError); - switch (frResult.GetResult()) - { - case EFeedbackResult::eResult_Cancel: - return TSubTaskBase::eSubResult_CancelRequest; + //log + TString strFormat = _T("Error %errno while calling fast move %srcpath -> %dstpath (TSubTaskFastMove)"); + strFormat.Replace(_T("%errno"), boost::lexical_cast(dwLastError).c_str()); + strFormat.Replace(_T("%srcpath"), spFileInfo->GetFullFilePath().ToString()); + strFormat.Replace(_T("%dstpath"), pathDestination.ToString()); + m_rLog.loge(strFormat.c_str()); - case EFeedbackResult::eResult_Retry: - bRetry = true; - break; + TFeedbackResult frResult = m_spFeedbackHandler->FileError(pathSrc.ToWString(), pathDestination.ToWString(), EFileError::eFastMoveError, dwLastError); + switch (frResult.GetResult()) + { + case EFeedbackResult::eResult_Cancel: + return TSubTaskBase::eSubResult_CancelRequest; - case EFeedbackResult::eResult_Pause: - return TSubTaskBase::eSubResult_PauseRequest; + case EFeedbackResult::eResult_Retry: + bRetry = true; + break; - case EFeedbackResult::eResult_Skip: - bSkip = true; - break; // just do nothing + case EFeedbackResult::eResult_Pause: + return TSubTaskBase::eSubResult_PauseRequest; - default: - BOOST_ASSERT(FALSE); // unknown result - THROW_CORE_EXCEPTION(eErr_UnhandledCase); - } + case EFeedbackResult::eResult_Skip: + bSkip = true; + return TSubTaskBase::eSubResult_Continue; + + default: + BOOST_ASSERT(FALSE); // unknown result + THROW_CORE_EXCEPTION(eErr_UnhandledCase); } - } while (bRetry); + if(WasKillRequested(frResult)) + return TSubTaskBase::eSubResult_KillRequest; + } + while (bRetry); + return TSubTaskBase::eSubResult_Continue; } @@ -399,15 +426,18 @@ case EFeedbackResult::eResult_Skip: bSkip = true; - break; // just do nothing + return TSubTaskBase::eSubResult_Continue; default: BOOST_ASSERT(FALSE); // unknown result THROW_CORE_EXCEPTION(eErr_UnhandledCase); } - } while (bRetry); + if(WasKillRequested(frResult)) + return TSubTaskBase::eSubResult_KillRequest; + } + while(bRetry); + return TSubTaskBase::eSubResult_Continue; } - } Index: src/libchcore/TFilesystemFeedbackWrapper.h =================================================================== diff -u -r25722a1d39e5d4bb49c5a60cbee3dda6c02cb193 -r89f857792bba8752de98ddd477949e45cef5ba5a --- src/libchcore/TFilesystemFeedbackWrapper.h (.../TFilesystemFeedbackWrapper.h) (revision 25722a1d39e5d4bb49c5a60cbee3dda6c02cb193) +++ src/libchcore/TFilesystemFeedbackWrapper.h (.../TFilesystemFeedbackWrapper.h) (revision 89f857792bba8752de98ddd477949e45cef5ba5a) @@ -26,10 +26,12 @@ namespace chcore { + class TWorkerThreadController; + class TFilesystemFeedbackWrapper { public: - TFilesystemFeedbackWrapper(const IFeedbackHandlerPtr& spFeedbackHandler, const IFilesystemPtr& spFilesystem, icpf::log_file& rLog); + TFilesystemFeedbackWrapper(const IFeedbackHandlerPtr& spFeedbackHandler, const IFilesystemPtr& spFilesystem, icpf::log_file& rLog, TWorkerThreadController& rThreadController); TSubTaskBase::ESubOperationResult CreateDirectoryFB(const TSmartPath& pathDirectory); TSubTaskBase::ESubOperationResult CheckForFreeSpaceFB(const TSmartPath& pathFirstSrc, const TSmartPath& pathDestination, unsigned long long ullNeededSize); @@ -44,9 +46,13 @@ TFileInfoPtr& spFileInfo, const TBasePathDataPtr& spBasePath, bool& bSkip); private: + bool WasKillRequested(const TFeedbackResult& rFeedbackResult) const; + + private: IFeedbackHandlerPtr m_spFeedbackHandler; IFilesystemPtr m_spFilesystem; icpf::log_file& m_rLog; + TWorkerThreadController& m_rThreadController; }; } Index: src/libchcore/TFilesystemFileFeedbackWrapper.cpp =================================================================== diff -u -r4d1f8110906889d56552771fb58a6de86bc54a29 -r89f857792bba8752de98ddd477949e45cef5ba5a --- src/libchcore/TFilesystemFileFeedbackWrapper.cpp (.../TFilesystemFileFeedbackWrapper.cpp) (revision 4d1f8110906889d56552771fb58a6de86bc54a29) +++ src/libchcore/TFilesystemFileFeedbackWrapper.cpp (.../TFilesystemFileFeedbackWrapper.cpp) (revision 89f857792bba8752de98ddd477949e45cef5ba5a) @@ -22,12 +22,14 @@ #include #include #include "TFileInfo.h" +#include "TWorkerThreadController.h" namespace chcore { - TFilesystemFileFeedbackWrapper::TFilesystemFileFeedbackWrapper(const IFeedbackHandlerPtr& spFeedbackHandler, icpf::log_file& rLog) : + TFilesystemFileFeedbackWrapper::TFilesystemFileFeedbackWrapper(const IFeedbackHandlerPtr& spFeedbackHandler, icpf::log_file& rLog, TWorkerThreadController& rThreadController) : m_spFeedbackHandler(spFeedbackHandler), - m_rLog(rLog) + m_rLog(rLog), + m_rThreadController(rThreadController) { } @@ -57,7 +59,7 @@ switch (frResult.GetResult()) { case EFeedbackResult::eResult_Skip: - break; // will return INVALID_HANDLE_VALUE + return TSubTaskBase::eSubResult_Continue; case EFeedbackResult::eResult_Cancel: { @@ -89,6 +91,9 @@ BOOST_ASSERT(FALSE); // unknown result THROW_CORE_EXCEPTION(eErr_UnhandledCase); } + + if(WasKillRequested(frResult)) + return TSubTaskBase::eSubResult_KillRequest; } while(bRetry); @@ -128,7 +133,6 @@ m_rLog.loge(strFormat.c_str()); bRetry = true; - break; } case EFeedbackResult::eResult_Cancel: @@ -143,7 +147,7 @@ } case EFeedbackResult::eResult_Skip: - break; // will return invalid handle value + return TSubTaskBase::eSubResult_Continue; case EFeedbackResult::eResult_Pause: return TSubTaskBase::eSubResult_PauseRequest; @@ -152,16 +156,23 @@ BOOST_ASSERT(FALSE); // unknown result THROW_CORE_EXCEPTION(eErr_UnhandledCase); } - } while (bRetry); + if(WasKillRequested(frResult)) + return TSubTaskBase::eSubResult_KillRequest; + } + while(bRetry); + return TSubTaskBase::eSubResult_Continue; } TSubTaskBase::ESubOperationResult TFilesystemFileFeedbackWrapper::OpenDestinationFileFB(const IFilesystemFilePtr& fileDst, const TFileInfoPtr& spSrcFileInfo, - unsigned long long& ullSeekTo, bool& bFreshlyCreated) + unsigned long long& ullSeekTo, + bool& bFreshlyCreated, + bool& bSkip) { bool bRetry = false; + bSkip = false; ullSeekTo = 0; bFreshlyCreated = true; @@ -191,7 +202,10 @@ if (eResult != TSubTaskBase::eSubResult_Continue) return eResult; else if (!fileDst->IsOpen()) + { + bSkip = true; return TSubTaskBase::eSubResult_Continue; + } // read info about the existing destination file, TFileInfoPtr spDstFileInfo(boost::make_shared()); @@ -203,13 +217,14 @@ { case EFeedbackResult::eResult_Overwrite: ullSeekTo = 0; - break; + return TSubTaskBase::eSubResult_Continue; case EFeedbackResult::eResult_CopyRest: ullSeekTo = spDstFileInfo->GetLength64(); - break; + return TSubTaskBase::eSubResult_Continue; case EFeedbackResult::eResult_Skip: + bSkip = true; return TSubTaskBase::eSubResult_Continue; case EFeedbackResult::eResult_Cancel: @@ -229,47 +244,50 @@ THROW_CORE_EXCEPTION(eErr_UnhandledCase); } } - else + + TFeedbackResult frResult = m_spFeedbackHandler->FileError(fileDst->GetFilePath().ToWString(), TString(), EFileError::eCreateError, dwLastError); + switch (frResult.GetResult()) { - TFeedbackResult frResult = m_spFeedbackHandler->FileError(fileDst->GetFilePath().ToWString(), TString(), EFileError::eCreateError, dwLastError); - switch (frResult.GetResult()) - { - case EFeedbackResult::eResult_Retry: - { - // log - TString strFormat = _T("Retrying [error %errno] to open destination file %path (CustomCopyFileFB)"); - strFormat.Replace(_T("%errno"), boost::lexical_cast(dwLastError).c_str()); - strFormat.Replace(_T("%path"), fileDst->GetFilePath().ToString()); - m_rLog.loge(strFormat.c_str()); + case EFeedbackResult::eResult_Retry: + { + // log + TString strFormat = _T("Retrying [error %errno] to open destination file %path (CustomCopyFileFB)"); + strFormat.Replace(_T("%errno"), boost::lexical_cast(dwLastError).c_str()); + strFormat.Replace(_T("%path"), fileDst->GetFilePath().ToString()); + m_rLog.loge(strFormat.c_str()); - bRetry = true; + bRetry = true; - break; - } - case EFeedbackResult::eResult_Cancel: - { - // log - TString strFormat = _T("Cancel request [error %errno] while opening destination file %path (CustomCopyFileFB)"); - strFormat.Replace(_T("%errno"), boost::lexical_cast(dwLastError).c_str()); - strFormat.Replace(_T("%path"), fileDst->GetFilePath().ToString()); - m_rLog.loge(strFormat.c_str()); + break; + } + case EFeedbackResult::eResult_Cancel: + { + // log + TString strFormat = _T("Cancel request [error %errno] while opening destination file %path (CustomCopyFileFB)"); + strFormat.Replace(_T("%errno"), boost::lexical_cast(dwLastError).c_str()); + strFormat.Replace(_T("%path"), fileDst->GetFilePath().ToString()); + m_rLog.loge(strFormat.c_str()); - return TSubTaskBase::eSubResult_CancelRequest; - } + return TSubTaskBase::eSubResult_CancelRequest; + } - case EFeedbackResult::eResult_Skip: - break; // will return invalid handle value + case EFeedbackResult::eResult_Skip: + bSkip = true; + return TSubTaskBase::eSubResult_Continue; - case EFeedbackResult::eResult_Pause: - return TSubTaskBase::eSubResult_PauseRequest; + case EFeedbackResult::eResult_Pause: + return TSubTaskBase::eSubResult_PauseRequest; - default: - BOOST_ASSERT(FALSE); // unknown result - THROW_CORE_EXCEPTION(eErr_UnhandledCase); - } + default: + BOOST_ASSERT(FALSE); // unknown result + THROW_CORE_EXCEPTION(eErr_UnhandledCase); } - } while (bRetry); + if(WasKillRequested(frResult)) + return TSubTaskBase::eSubResult_KillRequest; + } + while(bRetry); + return TSubTaskBase::eSubResult_Continue; } @@ -318,8 +336,12 @@ BOOST_ASSERT(FALSE); // unknown result THROW_CORE_EXCEPTION(eErr_UnhandledCase); } - } while (bRetry); + if(WasKillRequested(frResult)) + return TSubTaskBase::eSubResult_KillRequest; + } + while(bRetry); + return TSubTaskBase::eSubResult_Continue; } @@ -370,8 +392,12 @@ BOOST_ASSERT(FALSE); // unknown result THROW_CORE_EXCEPTION(eErr_UnhandledCase); } - } while (bRetry); + if(WasKillRequested(frResult)) + return TSubTaskBase::eSubResult_KillRequest; + } + while(bRetry); + return TSubTaskBase::eSubResult_Continue; } @@ -423,8 +449,12 @@ BOOST_ASSERT(FALSE); // unknown result THROW_CORE_EXCEPTION(eErr_UnhandledCase); } - } while (bRetry); + if(WasKillRequested(frResult)) + return TSubTaskBase::eSubResult_KillRequest; + } + while(bRetry); + return TSubTaskBase::eSubResult_Continue; } @@ -475,8 +505,19 @@ BOOST_ASSERT(FALSE); // unknown result THROW_CORE_EXCEPTION(eErr_UnhandledCase); } - } while (bRetry); + if(WasKillRequested(frResult)) + return TSubTaskBase::eSubResult_KillRequest; + } + while(bRetry); + return TSubTaskBase::eSubResult_Continue; } + + bool TFilesystemFileFeedbackWrapper::WasKillRequested(const TFeedbackResult& rFeedbackResult) const + { + if(m_rThreadController.KillRequested(rFeedbackResult.IsAutomatedReply() ? m_spFeedbackHandler->GetRetryInterval() : 0)) + return true; + return false; + } } Index: src/libchcore/TFilesystemFileFeedbackWrapper.h =================================================================== diff -u -r41383599835bbab64d854eed179a7db21a59c6bf -r89f857792bba8752de98ddd477949e45cef5ba5a --- src/libchcore/TFilesystemFileFeedbackWrapper.h (.../TFilesystemFileFeedbackWrapper.h) (revision 41383599835bbab64d854eed179a7db21a59c6bf) +++ src/libchcore/TFilesystemFileFeedbackWrapper.h (.../TFilesystemFileFeedbackWrapper.h) (revision 89f857792bba8752de98ddd477949e45cef5ba5a) @@ -28,15 +28,17 @@ namespace chcore { + class TWorkerThreadController; + class TFilesystemFileFeedbackWrapper { public: - TFilesystemFileFeedbackWrapper(const IFeedbackHandlerPtr& spFeedbackHandler, icpf::log_file& rLog); + TFilesystemFileFeedbackWrapper(const IFeedbackHandlerPtr& spFeedbackHandler, icpf::log_file& rLog, TWorkerThreadController& rThreadController); TSubTaskBase::ESubOperationResult OpenSourceFileFB(const IFilesystemFilePtr& fileSrc); TSubTaskBase::ESubOperationResult OpenExistingDestinationFileFB(const IFilesystemFilePtr& fileDst); TSubTaskBase::ESubOperationResult OpenDestinationFileFB(const IFilesystemFilePtr& fileDst, const TFileInfoPtr& spSrcFileInfo, - unsigned long long& ullSeekTo, bool& bFreshlyCreated); + unsigned long long& ullSeekTo, bool& bFreshlyCreated, bool& bSkip); TSubTaskBase::ESubOperationResult TruncateFileFB(const IFilesystemFilePtr& spFile, file_size_t fsNewSize, const TSmartPath& pathFile, bool& bSkip); @@ -50,9 +52,13 @@ TOverlappedDataBuffer& rBuffer, const TSmartPath& pathFile, bool& bSkip); private: + bool WasKillRequested(const TFeedbackResult& rFeedbackResult) const; + + private: IFeedbackHandlerPtr m_spFeedbackHandler; IFilesystemPtr m_spFilesystem; icpf::log_file& m_rLog; + TWorkerThreadController& m_rThreadController; }; } Index: src/libchcore/TSubTaskCopyMove.cpp =================================================================== diff -u -r4d1f8110906889d56552771fb58a6de86bc54a29 -r89f857792bba8752de98ddd477949e45cef5ba5a --- src/libchcore/TSubTaskCopyMove.cpp (.../TSubTaskCopyMove.cpp) (revision 4d1f8110906889d56552771fb58a6de86bc54a29) +++ src/libchcore/TSubTaskCopyMove.cpp (.../TSubTaskCopyMove.cpp) (revision 89f857792bba8752de98ddd477949e45cef5ba5a) @@ -91,7 +91,7 @@ IFilesystemPtr spFilesystem = GetContext().GetLocalFilesystem(); TBasePathDataContainerPtr spSrcPaths = GetContext().GetBasePaths(); - TFilesystemFeedbackWrapper tFilesystemFBWrapper(spFeedbackHandler, spFilesystem, rLog); + TFilesystemFeedbackWrapper tFilesystemFBWrapper(spFeedbackHandler, spFilesystem, rLog, rThreadController); // log rLog.logi(_T("Processing files/folders (ProcessFiles)")); @@ -201,21 +201,20 @@ // if moving - delete file (only if config flag is set) if(bMove && spFileInfo->IsProcessed() && !GetTaskPropValue(rConfig)) { - if(spFileInfo->IsReadOnly() && !GetTaskPropValue(rConfig)) - spFilesystem->SetAttributes(spFileInfo->GetFullFilePath(), FILE_ATTRIBUTE_NORMAL); - - spFilesystem->DeleteFile(spFileInfo->GetFullFilePath()); // there will be another try later, so we don't check - // if succeeded + tFilesystemFBWrapper.DeleteFileFB(spFileInfo, GetTaskPropValue(rConfig)); } } - // set a time - if(GetTaskPropValue(rConfig)) - spFilesystem->SetFileDirectoryTime(ccp.pathDstFile, spFileInfo->GetCreationTime(), spFileInfo->GetLastAccessTime(), spFileInfo->GetLastWriteTime()); // no error checking (but most probably it should be checked) + // only set attributes and times when file/dir had been processed successfully. + if(spFileInfo->IsProcessed()) + { + if(GetTaskPropValue(rConfig)) + spFilesystem->SetFileDirectoryTime(ccp.pathDstFile, spFileInfo->GetCreationTime(), spFileInfo->GetLastAccessTime(), spFileInfo->GetLastWriteTime()); // no error checking (but most probably it should be checked) - // attributes - if(GetTaskPropValue(rConfig)) - spFilesystem->SetAttributes(ccp.pathDstFile, spFileInfo->GetAttributes()); // as above + // attributes + if(GetTaskPropValue(rConfig)) + spFilesystem->SetAttributes(ccp.pathDstFile, spFileInfo->GetAttributes()); // as above + } } m_tSubTaskStats.SetCurrentIndex(fcIndex); @@ -281,7 +280,7 @@ const TConfig& rConfig = GetContext().GetConfig(); IFilesystemPtr spFilesystem = GetContext().GetLocalFilesystem(); - TFilesystemFileFeedbackWrapper tFileFBWrapper(spFeedbackHandler, rLog); + TFilesystemFileFeedbackWrapper tFileFBWrapper(spFeedbackHandler, rLog, rThreadController); TString strFormat; TSubTaskBase::ESubOperationResult eResult = TSubTaskBase::eSubResult_Continue; @@ -642,15 +641,14 @@ { // open destination file for case, when we start operation on this file (i.e. it is not resume of the // old operation) - eResult = rFileFBWrapper.OpenDestinationFileFB(spFileDst, pData->spSrcFile, ullSeekTo, bDstFileFreshlyCreated); + eResult = rFileFBWrapper.OpenDestinationFileFB(spFileDst, pData->spSrcFile, ullSeekTo, bDstFileFreshlyCreated, bSkip); if(eResult != TSubTaskBase::eSubResult_Continue) return eResult; - else if(!spFileDst->IsOpen()) + else if(bSkip) { AdjustProcessedSizeForSkip(pData->spSrcFile); pData->bProcessed = false; - bSkip = true; return TSubTaskBase::eSubResult_Continue; } } Index: src/libchcore/TSubTaskDelete.cpp =================================================================== diff -u -r25722a1d39e5d4bb49c5a60cbee3dda6c02cb193 -r89f857792bba8752de98ddd477949e45cef5ba5a --- src/libchcore/TSubTaskDelete.cpp (.../TSubTaskDelete.cpp) (revision 25722a1d39e5d4bb49c5a60cbee3dda6c02cb193) +++ src/libchcore/TSubTaskDelete.cpp (.../TSubTaskDelete.cpp) (revision 89f857792bba8752de98ddd477949e45cef5ba5a) @@ -68,7 +68,7 @@ TWorkerThreadController& rThreadController = GetContext().GetThreadController(); IFilesystemPtr spFilesystem = GetContext().GetLocalFilesystem(); - TFilesystemFeedbackWrapper tFilesystemFBWrapper(spFeedbackHandler, spFilesystem, rLog); + TFilesystemFeedbackWrapper tFilesystemFBWrapper(spFeedbackHandler, spFilesystem, rLog, rThreadController); // log rLog.logi(_T("Deleting files (DeleteFiles)...")); Index: src/libchcore/TSubTaskFastMove.cpp =================================================================== diff -u -r25722a1d39e5d4bb49c5a60cbee3dda6c02cb193 -r89f857792bba8752de98ddd477949e45cef5ba5a --- src/libchcore/TSubTaskFastMove.cpp (.../TSubTaskFastMove.cpp) (revision 25722a1d39e5d4bb49c5a60cbee3dda6c02cb193) +++ src/libchcore/TSubTaskFastMove.cpp (.../TSubTaskFastMove.cpp) (revision 89f857792bba8752de98ddd477949e45cef5ba5a) @@ -73,7 +73,7 @@ const TFileFiltersArray& rafFilters = GetContext().GetFilters(); IFilesystemPtr spFilesystem = GetContext().GetLocalFilesystem(); - TFilesystemFeedbackWrapper tFilesystemFBWrapper(spFeedbackHandler, spFilesystem, rLog); + TFilesystemFeedbackWrapper tFilesystemFBWrapper(spFeedbackHandler, spFilesystem, rLog, rThreadController); rLog.logi(_T("Performing initial fast-move operation...")); Index: src/libchcore/TSubTaskScanDirectory.cpp =================================================================== diff -u -r25722a1d39e5d4bb49c5a60cbee3dda6c02cb193 -r89f857792bba8752de98ddd477949e45cef5ba5a --- src/libchcore/TSubTaskScanDirectory.cpp (.../TSubTaskScanDirectory.cpp) (revision 25722a1d39e5d4bb49c5a60cbee3dda6c02cb193) +++ src/libchcore/TSubTaskScanDirectory.cpp (.../TSubTaskScanDirectory.cpp) (revision 89f857792bba8752de98ddd477949e45cef5ba5a) @@ -74,7 +74,7 @@ const TFileFiltersArray& rafFilters = GetContext().GetFilters(); IFilesystemPtr spFilesystem = GetContext().GetLocalFilesystem(); - TFilesystemFeedbackWrapper tFilesystemFBWrapper(spFeedbackHandler, spFilesystem, rLog); + TFilesystemFeedbackWrapper tFilesystemFBWrapper(spFeedbackHandler, spFilesystem, rLog, rThreadController); rLog.logi(_T("Searching for files...")); Index: src/libchcore/TWorkerThreadController.cpp =================================================================== diff -u -r0c48142d3db406c32c05d7afdf77da45b2459b34 -r89f857792bba8752de98ddd477949e45cef5ba5a --- src/libchcore/TWorkerThreadController.cpp (.../TWorkerThreadController.cpp) (revision 0c48142d3db406c32c05d7afdf77da45b2459b34) +++ src/libchcore/TWorkerThreadController.cpp (.../TWorkerThreadController.cpp) (revision 89f857792bba8752de98ddd477949e45cef5ba5a) @@ -95,11 +95,11 @@ SignalThreadToStop(lock); } - void TWorkerThreadController::WaitForThreadToExit() + void TWorkerThreadController::WaitForThreadToExit(DWORD dwMiliseconds) { boost::upgrade_lock lock(m_lock); - DWORD dwRes = WaitForSingleObject(m_hThread, INFINITE); + DWORD dwRes = WaitForSingleObject(m_hThread, dwMiliseconds); if (dwRes == WAIT_OBJECT_0) { if (!::ResetEvent(m_hKillThread)) @@ -198,12 +198,12 @@ THROW_CORE_EXCEPTION_WIN32(eErr_CannotSetEvent, GetLastError()); } - void TWorkerThreadController::WaitForThreadToExit(boost::upgrade_lock& rUpgradeLock) + void TWorkerThreadController::WaitForThreadToExit(boost::upgrade_lock& rUpgradeLock, DWORD dwMiliseconds) { if (!m_hThread) return; - DWORD dwRes = WaitForSingleObject(m_hThread, INFINITE); + DWORD dwRes = WaitForSingleObject(m_hThread, dwMiliseconds); if (dwRes == WAIT_OBJECT_0) { if (!::ResetEvent(m_hKillThread)) Index: src/libchcore/TWorkerThreadController.h =================================================================== diff -u -re96806b7f8ff7ca7e9f4afbea603e6351a3dc3e3 -r89f857792bba8752de98ddd477949e45cef5ba5a --- src/libchcore/TWorkerThreadController.h (.../TWorkerThreadController.h) (revision e96806b7f8ff7ca7e9f4afbea603e6351a3dc3e3) +++ src/libchcore/TWorkerThreadController.h (.../TWorkerThreadController.h) (revision 89f857792bba8752de98ddd477949e45cef5ba5a) @@ -39,20 +39,20 @@ // methods to be used outside of the thread being controlled void StartThread(PTHREAD_START_ROUTINE pThreadFunction, PVOID pThreadParam, int iPriority = THREAD_PRIORITY_NORMAL); void SignalThreadToStop(); - void WaitForThreadToExit(); + void WaitForThreadToExit(DWORD dwMiliseconds = INFINITE); void StopThread(); void ChangePriority(int iPriority); // methods to be used only inside the thread being controlled bool KillRequested(DWORD dwWaitForSignal = 0); - HANDLE GetKillThreadHandle() const; + protected: void RemoveZombieData(boost::upgrade_lock& rUpgradeLock); void SignalThreadToStop(boost::upgrade_lock& rUpgradeLock); - void WaitForThreadToExit(boost::upgrade_lock& rUpgradeLock); + void WaitForThreadToExit(boost::upgrade_lock& rUpgradeLock, DWORD dwMiliseconds = INFINITE); private: TWorkerThreadController(const TWorkerThreadController&);