Index: src/libchcore/TCoreException.h =================================================================== diff -u -r0c48142d3db406c32c05d7afdf77da45b2459b34 -r09d769045d1d5c45d8df16d209c754b872348c26 --- src/libchcore/TCoreException.h (.../TCoreException.h) (revision 0c48142d3db406c32c05d7afdf77da45b2459b34) +++ src/libchcore/TCoreException.h (.../TCoreException.h) (revision 09d769045d1d5c45d8df16d209c754b872348c26) @@ -25,10 +25,10 @@ // throws core exception object #define THROW_CORE_EXCEPTION(error_code)\ - throw chcore::TCoreException(error_code, L"", __FILEW__, __LINE__, __FUNCTIONW__) + throw ::chcore::TCoreException(error_code, L"", __FILEW__, __LINE__, __FUNCTIONW__) #define THROW_CORE_EXCEPTION_MSG(error_code, msg)\ - throw chcore::TCoreException(error_code, msg, __FILEW__, __LINE__, __FUNCTIONW__) + throw ::chcore::TCoreException(error_code, msg, __FILEW__, __LINE__, __FUNCTIONW__) namespace chcore { Index: src/libchcore/TFilesystemFeedbackWrapper.cpp =================================================================== diff -u --- src/libchcore/TFilesystemFeedbackWrapper.cpp (revision 0) +++ src/libchcore/TFilesystemFeedbackWrapper.cpp (revision 09d769045d1d5c45d8df16d209c754b872348c26) @@ -0,0 +1,175 @@ +// ============================================================================ +// Copyright (C) 2001-2015 by Jozef Starosczyk +// ixen@copyhandler.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License +// (version 2) as published by the Free Software Foundation; +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// ============================================================================ +#include "stdafx.h" +#include "TFilesystemFeedbackWrapper.h" +#include +#include "TFileException.h" + +namespace chcore +{ + TFilesystemFeedbackWrapper::TFilesystemFeedbackWrapper(const IFilesystemPtr& spFilesystem, icpf::log_file& rLog) : + m_spFilesystem(spFilesystem), + m_rLog(rLog) + { + if (!spFilesystem) + THROW_CORE_EXCEPTION_MSG(eErr_InvalidArgument, L"Filesystem not provided"); + } + + TSubTaskBase::ESubOperationResult TFilesystemFeedbackWrapper::CreateDirectoryFB(const IFeedbackHandlerPtr& spFeedbackHandler, const TSmartPath& pathDirectory) + { + bool bRetry = false; + do + { + bRetry = false; + + DWORD dwLastError = ERROR_SUCCESS; + try + { + m_spFilesystem->CreateDirectory(pathDirectory, false); + return TSubTaskBase::eSubResult_Continue; + } + catch (const TFileException& e) + { + dwLastError = e.GetNativeError(); + } + + if (dwLastError == ERROR_ALREADY_EXISTS) + return TSubTaskBase::eSubResult_Continue; + + // log + TString strFormat; + strFormat = _T("Error %errno while calling CreateDirectory %path (ProcessFiles)"); + strFormat.Replace(_T("%errno"), boost::lexical_cast(dwLastError).c_str()); + strFormat.Replace(_T("%path"), pathDirectory.ToString()); + m_rLog.loge(strFormat.c_str()); + + EFeedbackResult frResult = spFeedbackHandler->FileError(pathDirectory.ToWString(), TString(), EFileError::eCreateError, dwLastError); + switch (frResult) + { + case EFeedbackResult::eResult_Cancel: + return TSubTaskBase::eSubResult_CancelRequest; + + case EFeedbackResult::eResult_Retry: + bRetry = true; + break; + + case EFeedbackResult::eResult_Pause: + return TSubTaskBase::eSubResult_PauseRequest; + + case EFeedbackResult::eResult_Skip: + break; // just do nothing + + default: + BOOST_ASSERT(FALSE); // unknown result + THROW_CORE_EXCEPTION(eErr_UnhandledCase); + } + } + while (bRetry); + + return TSubTaskBase::eSubResult_Continue; + } + + TSubTaskBase::ESubOperationResult TFilesystemFeedbackWrapper::CheckForFreeSpaceFB(const IFeedbackHandlerPtr& spFeedbackHandler, const TSmartPath& pathFirstSrc, const TSmartPath& pathDestination, unsigned long long ullNeededSize) + { + unsigned long long ullAvailableSize = 0; + bool bRetry = false; + + do + { + bRetry = false; + + m_rLog.logi(_T("Checking for free space on destination disk...")); + + // get free space + DWORD dwLastError = ERROR_SUCCESS; + bool bCheckFailed = false; + try + { + m_spFilesystem->GetDynamicFreeSpace(pathDestination, ullAvailableSize); + } + catch (const TFileException& e) + { + dwLastError = e.GetNativeError(); + bCheckFailed = true; + } + + if (bCheckFailed) + { + TString strFormat; + strFormat = _T("Error %errno while checking free space at %path"); + strFormat.Replace(_T("%errno"), boost::lexical_cast(dwLastError).c_str()); + strFormat.Replace(_T("%path"), pathDestination.ToString()); + m_rLog.loge(strFormat.c_str()); + + EFeedbackResult frResult = spFeedbackHandler->FileError(pathDestination.ToWString(), TString(), EFileError::eCheckForFreeSpace, dwLastError); + switch (frResult) + { + case EFeedbackResult::eResult_Cancel: + return TSubTaskBase::eSubResult_CancelRequest; + + case EFeedbackResult::eResult_Retry: + bRetry = true; + continue; + + case EFeedbackResult::eResult_Pause: + return TSubTaskBase::eSubResult_PauseRequest; + + case EFeedbackResult::eResult_Skip: + return TSubTaskBase::eSubResult_Continue; + + default: + BOOST_ASSERT(FALSE); // unknown result + THROW_CORE_EXCEPTION(eErr_UnhandledCase); + } + } + + if (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()); + + EFeedbackResult frResult = spFeedbackHandler->NotEnoughSpace(pathFirstSrc.ToWString(), pathDestination.ToWString(), ullNeededSize); + switch (frResult) + { + case EFeedbackResult::eResult_Cancel: + m_rLog.logi(_T("Cancel request while checking for free space on disk.")); + return TSubTaskBase::eSubResult_CancelRequest; + + case EFeedbackResult::eResult_Retry: + m_rLog.logi(_T("Retrying to read drive's free space...")); + bRetry = true; + break; + + case EFeedbackResult::eResult_Ignore: + m_rLog.logi(_T("Ignored warning about not enough place on disk to copy data.")); + return TSubTaskBase::eSubResult_Continue; + + default: + BOOST_ASSERT(FALSE); // unknown result + THROW_CORE_EXCEPTION(eErr_UnhandledCase); + } + } + } while (bRetry); + + return TSubTaskBase::eSubResult_Continue; + } + +} Index: src/libchcore/TFilesystemFeedbackWrapper.h =================================================================== diff -u --- src/libchcore/TFilesystemFeedbackWrapper.h (revision 0) +++ src/libchcore/TFilesystemFeedbackWrapper.h (revision 09d769045d1d5c45d8df16d209c754b872348c26) @@ -0,0 +1,43 @@ +// ============================================================================ +// Copyright (C) 2001-2015 by Jozef Starosczyk +// ixen@copyhandler.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License +// (version 2) as published by the Free Software Foundation; +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// ============================================================================ +#ifndef __TFILESYSTEMFEEDBACKWRAPPER_H__ +#define __TFILESYSTEMFEEDBACKWRAPPER_H__ + +#include "libchcore.h" +#include "IFilesystem.h" +#include "TSubTaskBase.h" +#include "..\libicpf\log.h" + +namespace chcore +{ + class TFilesystemFeedbackWrapper + { + public: + TFilesystemFeedbackWrapper(const IFilesystemPtr& spFilesystem, icpf::log_file& rLog); + + TSubTaskBase::ESubOperationResult CreateDirectoryFB(const IFeedbackHandlerPtr& spFeedbackHandler, const TSmartPath& pathDirectory); + TSubTaskBase::ESubOperationResult CheckForFreeSpaceFB(const IFeedbackHandlerPtr& spFeedbackHandler, const TSmartPath& pathFirstSrc, const TSmartPath& pathDestination, unsigned long long ullNeededSize); + + private: + IFilesystemPtr m_spFilesystem; + icpf::log_file& m_rLog; + }; +} + +#endif Index: src/libchcore/TFilesystemFileFeedbackWrapper.cpp =================================================================== diff -u --- src/libchcore/TFilesystemFileFeedbackWrapper.cpp (revision 0) +++ src/libchcore/TFilesystemFileFeedbackWrapper.cpp (revision 09d769045d1d5c45d8df16d209c754b872348c26) @@ -0,0 +1,363 @@ +// ============================================================================ +// Copyright (C) 2001-2015 by Jozef Starosczyk +// ixen@copyhandler.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License +// (version 2) as published by the Free Software Foundation; +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// ============================================================================ +#include "stdafx.h" +#include "TFilesystemFileFeedbackWrapper.h" +#include "TFileException.h" +#include + +namespace chcore +{ + TFilesystemFileFeedbackWrapper::TFilesystemFileFeedbackWrapper(icpf::log_file& rLog) : + m_rLog(rLog) + { + } + + TSubTaskBase::ESubOperationResult TFilesystemFileFeedbackWrapper::OpenSourceFileFB(const IFeedbackHandlerPtr& spFeedbackHandler, const IFilesystemFilePtr& fileSrc) + { + bool bRetry = false; + + fileSrc->Close(); + + do + { + bRetry = false; + DWORD dwLastError = ERROR_SUCCESS; + + try + { + fileSrc->OpenExistingForReading(); + + return TSubTaskBase::eSubResult_Continue; + } + catch (const TFileException& e) + { + dwLastError = e.GetNativeError(); + } + + EFeedbackResult frResult = spFeedbackHandler->FileError(fileSrc->GetFilePath().ToWString(), TString(), EFileError::eCreateError, dwLastError); + switch (frResult) + { + case EFeedbackResult::eResult_Skip: + break; // will return INVALID_HANDLE_VALUE + + 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"), fileSrc->GetFilePath().ToString()); + m_rLog.loge(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"), fileSrc->GetFilePath().ToString()); + m_rLog.loge(strFormat.c_str()); + + bRetry = true; + break; + } + + default: + BOOST_ASSERT(FALSE); // unknown result + THROW_CORE_EXCEPTION(eErr_UnhandledCase); + } + } while (bRetry); + + return TSubTaskBase::eSubResult_Continue; + } + + TSubTaskBase::ESubOperationResult TFilesystemFileFeedbackWrapper::OpenExistingDestinationFileFB(const IFeedbackHandlerPtr& spFeedbackHandler, const IFilesystemFilePtr& fileDst) + { + bool bRetry = false; + + fileDst->Close(); + + do + { + bRetry = false; + + DWORD dwLastError = ERROR_SUCCESS; + try + { + fileDst->OpenExistingForWriting(); + return TSubTaskBase::eSubResult_Continue; + } + catch (const TFileException& e) + { + dwLastError = e.GetNativeError(); + } + + EFeedbackResult frResult = spFeedbackHandler->FileError(fileDst->GetFilePath().ToWString(), TString(), EFileError::eCreateError, dwLastError); + switch (frResult) + { + 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; + + 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; + } + + case EFeedbackResult::eResult_Skip: + break; // will return invalid handle value + + case EFeedbackResult::eResult_Pause: + return TSubTaskBase::eSubResult_PauseRequest; + + default: + BOOST_ASSERT(FALSE); // unknown result + THROW_CORE_EXCEPTION(eErr_UnhandledCase); + } + } while (bRetry); + + return TSubTaskBase::eSubResult_Continue; + } + + TSubTaskBase::ESubOperationResult TFilesystemFileFeedbackWrapper::TruncateFileFB(const IFeedbackHandlerPtr& spFeedbackHandler, const IFilesystemFilePtr& spFile, file_size_t fsNewSize, const TSmartPath& pathFile, bool& bSkip) + { + bSkip = false; + + bool bRetry = false; + do + { + DWORD dwLastError = ERROR_SUCCESS; + + try + { + spFile->Truncate(fsNewSize); + return TSubTaskBase::eSubResult_Continue; + } + catch (const TFileException& e) + { + dwLastError = e.GetNativeError(); + } + + TString strFormat = _T("Error %errno while truncating file %path to 0"); + strFormat.Replace(_t("%errno"), boost::lexical_cast(dwLastError).c_str()); + strFormat.Replace(_t("%path"), pathFile.ToString()); + m_rLog.loge(strFormat.c_str()); + + EFeedbackResult frResult = spFeedbackHandler->FileError(pathFile.ToWString(), TString(), EFileError::eResizeError, dwLastError); + switch (frResult) + { + case EFeedbackResult::eResult_Cancel: + return TSubTaskBase::eSubResult_CancelRequest; + + case EFeedbackResult::eResult_Retry: + bRetry = true; + break; + + case EFeedbackResult::eResult_Pause: + return TSubTaskBase::eSubResult_PauseRequest; + + case EFeedbackResult::eResult_Skip: + bSkip = true; + return TSubTaskBase::eSubResult_Continue; + + default: + BOOST_ASSERT(FALSE); // unknown result + THROW_CORE_EXCEPTION(eErr_UnhandledCase); + } + } while (bRetry); + + return TSubTaskBase::eSubResult_Continue; + } + + TSubTaskBase::ESubOperationResult TFilesystemFileFeedbackWrapper::ReadFileFB(const IFeedbackHandlerPtr& spFeedbackHandler, const IFilesystemFilePtr& spFile, TOverlappedDataBuffer& rBuffer, const TSmartPath& pathFile, bool& bSkip) + { + bSkip = false; + bool bRetry = false; + do + { + bRetry = false; + + DWORD dwLastError = ERROR_SUCCESS; + + try + { + spFile->ReadFile(rBuffer); + return TSubTaskBase::eSubResult_Continue; + } + catch (const TFileException& e) + { + dwLastError = e.GetNativeError(); + } + + TString strFormat = _T("Error %errno while requesting read of %count bytes from source file %path (CustomCopyFileFB)"); + strFormat.Replace(_t("%errno"), boost::lexical_cast(dwLastError).c_str()); + strFormat.Replace(_t("%count"), boost::lexical_cast(rBuffer.GetRequestedDataSize()).c_str()); + strFormat.Replace(_t("%path"), pathFile.ToString()); + m_rLog.loge(strFormat.c_str()); + + EFeedbackResult frResult = spFeedbackHandler->FileError(pathFile.ToWString(), TString(), EFileError::eReadError, dwLastError); + switch (frResult) + { + case EFeedbackResult::eResult_Cancel: + return TSubTaskBase::eSubResult_CancelRequest; + + case EFeedbackResult::eResult_Retry: + bRetry = true; + break; + + case EFeedbackResult::eResult_Pause: + return TSubTaskBase::eSubResult_PauseRequest; + + case EFeedbackResult::eResult_Skip: + bSkip = true; + return TSubTaskBase::eSubResult_Continue; + + default: + BOOST_ASSERT(FALSE); // unknown result + THROW_CORE_EXCEPTION(eErr_UnhandledCase); + } + } while (bRetry); + + return TSubTaskBase::eSubResult_Continue; + } + + TSubTaskBase::ESubOperationResult TFilesystemFileFeedbackWrapper::WriteFileFB(const IFeedbackHandlerPtr& spFeedbackHandler, const IFilesystemFilePtr& spFile, TOverlappedDataBuffer& rBuffer, const TSmartPath& pathFile, bool& bSkip) + { + bSkip = false; + + bool bRetry = false; + do + { + bRetry = false; + + DWORD dwLastError = ERROR_SUCCESS; + + try + { + spFile->WriteFile(rBuffer); + return TSubTaskBase::eSubResult_Continue; + } + catch (const TFileException& e) + { + dwLastError = e.GetNativeError(); + } + + TString strFormat = _T("Error %errno while trying to write %count bytes to destination file %path (CustomCopyFileFB)"); + strFormat.Replace(_t("%errno"), boost::lexical_cast(dwLastError).c_str()); + strFormat.Replace(_t("%count"), boost::lexical_cast(rBuffer.GetBytesTransferred()).c_str()); + strFormat.Replace(_t("%path"), pathFile.ToString()); + m_rLog.loge(strFormat.c_str()); + + EFeedbackResult frResult = spFeedbackHandler->FileError(pathFile.ToWString(), TString(), EFileError::eWriteError, dwLastError); + switch (frResult) + { + case EFeedbackResult::eResult_Cancel: + return TSubTaskBase::eSubResult_CancelRequest; + + case EFeedbackResult::eResult_Retry: + bRetry = true; + break; + + case EFeedbackResult::eResult_Pause: + return TSubTaskBase::eSubResult_PauseRequest; + + case EFeedbackResult::eResult_Skip: + bSkip = true; + return TSubTaskBase::eSubResult_Continue; + + default: + BOOST_ASSERT(FALSE); // unknown result + THROW_CORE_EXCEPTION(eErr_UnhandledCase); + } + } while (bRetry); + + return TSubTaskBase::eSubResult_Continue; + } + + TSubTaskBase::ESubOperationResult TFilesystemFileFeedbackWrapper::FinalizeFileFB(const IFeedbackHandlerPtr& spFeedbackHandler, const IFilesystemFilePtr& spFile, TOverlappedDataBuffer& rBuffer, const TSmartPath& pathFile, bool& bSkip) + { + bSkip = false; + + bool bRetry = false; + do + { + bRetry = false; + + DWORD dwLastError = ERROR_SUCCESS; + + try + { + spFile->FinalizeFile(rBuffer); + return TSubTaskBase::eSubResult_Continue; + } + catch (const TFileException& e) + { + dwLastError = e.GetNativeError(); + } + + TString strFormat = _T("Error %errno while trying to finalize file %path (CustomCopyFileFB)"); + strFormat.Replace(_t("%errno"), boost::lexical_cast(dwLastError).c_str()); + strFormat.Replace(_t("%path"), pathFile.ToString()); + m_rLog.loge(strFormat.c_str()); + + EFeedbackResult frResult = spFeedbackHandler->FileError(pathFile.ToWString(), TString(), EFileError::eFinalizeError, dwLastError); + switch (frResult) + { + case EFeedbackResult::eResult_Cancel: + return TSubTaskBase::eSubResult_CancelRequest; + + case EFeedbackResult::eResult_Retry: + bRetry = true; + break; + + case EFeedbackResult::eResult_Pause: + return TSubTaskBase::eSubResult_PauseRequest; + + case EFeedbackResult::eResult_Skip: + bSkip = true; + return TSubTaskBase::eSubResult_Continue; + + default: + BOOST_ASSERT(FALSE); // unknown result + THROW_CORE_EXCEPTION(eErr_UnhandledCase); + } + } while (bRetry); + + return TSubTaskBase::eSubResult_Continue; + } + +} Index: src/libchcore/TFilesystemFileFeedbackWrapper.h =================================================================== diff -u --- src/libchcore/TFilesystemFileFeedbackWrapper.h (revision 0) +++ src/libchcore/TFilesystemFileFeedbackWrapper.h (revision 09d769045d1d5c45d8df16d209c754b872348c26) @@ -0,0 +1,54 @@ +// ============================================================================ +// Copyright (C) 2001-2015 by Jozef Starosczyk +// ixen@copyhandler.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License +// (version 2) as published by the Free Software Foundation; +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// ============================================================================ +#ifndef __TFILESYSTEMFILEFEEDBACKWRAPPER_H__ +#define __TFILESYSTEMFILEFEEDBACKWRAPPER_H__ + +#include "libchcore.h" +#include "IFilesystemFile.h" +#include "..\libicpf\log.h" +#include "TSubTaskBase.h" +#include "IFeedbackHandler.h" + +namespace chcore +{ + class TFilesystemFileFeedbackWrapper + { + public: + TFilesystemFileFeedbackWrapper(icpf::log_file& rLog); + + TSubTaskBase::ESubOperationResult OpenSourceFileFB(const IFeedbackHandlerPtr& spFeedbackHandler, const IFilesystemFilePtr& fileSrc); + TSubTaskBase::ESubOperationResult OpenExistingDestinationFileFB(const IFeedbackHandlerPtr& spFeedbackHandler, const IFilesystemFilePtr& fileDst); + + TSubTaskBase::ESubOperationResult TruncateFileFB(const IFeedbackHandlerPtr& spFeedbackHandler, const IFilesystemFilePtr& spFile, file_size_t fsNewSize, + const TSmartPath& pathFile, bool& bSkip); + + TSubTaskBase::ESubOperationResult ReadFileFB(const IFeedbackHandlerPtr& spFeedbackHandler, const IFilesystemFilePtr& spFile, + TOverlappedDataBuffer& rBuffer, const TSmartPath& pathFile, bool& bSkip); + TSubTaskBase::ESubOperationResult WriteFileFB(const IFeedbackHandlerPtr& spFeedbackHandler, const IFilesystemFilePtr& spFile, + TOverlappedDataBuffer& rBuffer, const TSmartPath& pathFile, bool& bSkip); + + TSubTaskBase::ESubOperationResult FinalizeFileFB(const IFeedbackHandlerPtr& spFeedbackHandler, const IFilesystemFilePtr& spFile, + TOverlappedDataBuffer& rBuffer, const TSmartPath& pathFile, bool& bSkip); + + private: + icpf::log_file& m_rLog; + }; +} + +#endif Index: src/libchcore/TSubTaskCopyMove.cpp =================================================================== diff -u -r3be63f912be8157e7f1dc2dad443237dce1efa7c -r09d769045d1d5c45d8df16d209c754b872348c26 --- src/libchcore/TSubTaskCopyMove.cpp (.../TSubTaskCopyMove.cpp) (revision 3be63f912be8157e7f1dc2dad443237dce1efa7c) +++ src/libchcore/TSubTaskCopyMove.cpp (.../TSubTaskCopyMove.cpp) (revision 09d769045d1d5c45d8df16d209c754b872348c26) @@ -47,6 +47,8 @@ #include #include "TTaskConfigBufferSizes.h" #include "TFileException.h" +#include "TFilesystemFeedbackWrapper.h" +#include "TFilesystemFileFeedbackWrapper.h" namespace chcore { @@ -87,7 +89,10 @@ const TConfig& rConfig = GetContext().GetConfig(); TSmartPath pathDestination = GetContext().GetDestinationPath(); IFilesystemPtr spFilesystem = GetContext().GetLocalFilesystem(); + TBasePathDataContainerPtr spSrcPaths = GetContext().GetBasePaths(); + TFilesystemFeedbackWrapper tFilesystemFBWrapper(spFilesystem, rLog); + // log rLog.logi(_T("Processing files/folders (ProcessFiles)")); @@ -103,7 +108,9 @@ } // now it's time to check if there is enough space on destination device - TSubTaskBase::ESubOperationResult eResult = CheckForFreeSpaceFB(spFeedbackHandler); + unsigned long long ullNeededSize = rFilesCache.CalculateTotalSize() - rFilesCache.CalculatePartialSize(m_tSubTaskStats.GetCurrentIndex()); + TSmartPath pathSingleSrc = spSrcPaths->GetAt(0)->GetSrcPath(); + TSubTaskBase::ESubOperationResult eResult = tFilesystemFBWrapper.CheckForFreeSpaceFB(spFeedbackHandler, pathSingleSrc, pathDestination, ullNeededSize); if(eResult != TSubTaskBase::eSubResult_Continue) return eResult; @@ -169,7 +176,7 @@ // if folder - create it if(spFileInfo->IsDirectory()) { - eResult = CreateDirectoryFB(spFeedbackHandler, ccp.pathDstFile); + eResult = tFilesystemFBWrapper.CreateDirectoryFB(spFeedbackHandler, ccp.pathDstFile); if(eResult != TSubTaskBase::eSubResult_Continue) return eResult; @@ -274,6 +281,8 @@ const TConfig& rConfig = GetContext().GetConfig(); IFilesystemPtr spFilesystem = GetContext().GetLocalFilesystem(); + TFilesystemFileFeedbackWrapper tFileFBWrapper(rLog); + TString strFormat; TSubTaskBase::ESubOperationResult eResult = TSubTaskBase::eSubResult_Continue; @@ -288,7 +297,7 @@ IFilesystemFilePtr fileDst = spFilesystem->CreateFileObject(pData->pathDstFile, bNoBuffer); bool bSkip = false; - eResult = OpenSrcAndDstFilesFB(spFeedbackHandler, pData, fileSrc, fileDst, bSkip); + eResult = OpenSrcAndDstFilesFB(tFileFBWrapper, spFeedbackHandler, pData, fileSrc, fileDst, bSkip); if(eResult != TSubTaskBase::eSubResult_Continue) return eResult; else if(bSkip) @@ -355,7 +364,7 @@ pBuffer->InitForRead(ullNextReadPos, dwToRead); ullNextReadPos += dwToRead; - eResult = ReadFileFB(spFeedbackHandler, fileSrc, *pBuffer, pData->spSrcFile->GetFullFilePath(), bSkip); + eResult = tFileFBWrapper.ReadFileFB(spFeedbackHandler, fileSrc, *pBuffer, pData->spSrcFile->GetFullFilePath(), bSkip); if(eResult != TSubTaskBase::eSubResult_Continue) return eResult; else if(bSkip) @@ -382,7 +391,7 @@ if(eResult == TSubTaskBase::eSubResult_Retry) { // re-request read of the same data - eResult = ReadFileFB(spFeedbackHandler, fileSrc, *pBuffer, pData->spSrcFile->GetFullFilePath(), bSkip); + eResult = tFileFBWrapper.ReadFileFB(spFeedbackHandler, fileSrc, *pBuffer, pData->spSrcFile->GetFullFilePath(), bSkip); if(eResult != TSubTaskBase::eSubResult_Continue) return eResult; else if(bSkip) @@ -407,7 +416,7 @@ { pBuffer->InitForWrite(); - eResult = WriteFileFB(spFeedbackHandler, fileDst, *pBuffer, pData->pathDstFile, bSkip); + eResult = tFileFBWrapper.WriteFileFB(spFeedbackHandler, fileDst, *pBuffer, pData->pathDstFile, bSkip); if(eResult != TSubTaskBase::eSubResult_Continue) return eResult; else if(bSkip) @@ -433,7 +442,7 @@ eResult = HandleWriteError(spFeedbackHandler, *pBuffer, pData->spSrcFile->GetFullFilePath(), bSkip); if(eResult == TSubTaskBase::eSubResult_Retry) { - eResult = WriteFileFB(spFeedbackHandler, fileDst, *pBuffer, pData->pathDstFile, bSkip); + eResult = tFileFBWrapper.WriteFileFB(spFeedbackHandler, fileDst, *pBuffer, pData->pathDstFile, bSkip); if(eResult != TSubTaskBase::eSubResult_Continue) return eResult; else if(bSkip) @@ -456,7 +465,7 @@ } else { - eResult = FinalizeFileFB(spFeedbackHandler, fileDst, *pBuffer, pData->pathDstFile, bSkip); + eResult = tFileFBWrapper.FinalizeFileFB(spFeedbackHandler, fileDst, *pBuffer, pData->pathDstFile, bSkip); if (eResult != TSubTaskBase::eSubResult_Continue) return eResult; else if (bSkip) @@ -535,7 +544,7 @@ m_tSubTaskStats.AdjustProcessedSize(m_tSubTaskStats.GetCurrentItemProcessedSize(), spSrcFileInfo->GetLength64()); } - TSubTaskCopyMove::ESubOperationResult TSubTaskCopyMove::OpenSrcAndDstFilesFB(const IFeedbackHandlerPtr& spFeedbackHandler, CUSTOM_COPY_PARAMS* pData, + TSubTaskCopyMove::ESubOperationResult TSubTaskCopyMove::OpenSrcAndDstFilesFB(TFilesystemFileFeedbackWrapper& rFileFBWrapper, const IFeedbackHandlerPtr& spFeedbackHandler, CUSTOM_COPY_PARAMS* pData, const IFilesystemFilePtr& spFileSrc, const IFilesystemFilePtr& spFileDst, bool& bSkip) { const TConfig& rConfig = GetContext().GetConfig(); @@ -546,7 +555,7 @@ unsigned long long ullProcessedSize = m_tSubTaskStats.GetCurrentItemProcessedSize(); // first open the source file and handle any failures - TSubTaskCopyMove::ESubOperationResult eResult = OpenSourceFileFB(spFeedbackHandler, spFileSrc); + TSubTaskCopyMove::ESubOperationResult eResult = rFileFBWrapper.OpenSourceFileFB(spFeedbackHandler, spFileSrc); if(eResult != TSubTaskBase::eSubResult_Continue) return eResult; else if(!spFileSrc->IsOpen()) @@ -604,7 +613,7 @@ // we are resuming previous operation if(bContinue) { - eResult = OpenExistingDestinationFileFB(spFeedbackHandler, spFileDst); + eResult = rFileFBWrapper.OpenExistingDestinationFileFB(spFeedbackHandler, spFileDst); if (eResult != TSubTaskBase::eSubResult_Continue) return eResult; else if (!spFileDst->IsOpen()) @@ -624,7 +633,7 @@ { // open destination file for case, when we start operation on this file (i.e. it is not resume of the // old operation) - eResult = OpenDestinationFileFB(spFeedbackHandler, spFileDst, pData->spSrcFile, ullSeekTo, bDstFileFreshlyCreated); + eResult = OpenDestinationFileFB(rFileFBWrapper, spFeedbackHandler, spFileDst, pData->spSrcFile, ullSeekTo, bDstFileFreshlyCreated); if(eResult != TSubTaskBase::eSubResult_Continue) return eResult; else if(!spFileDst->IsOpen()) @@ -661,7 +670,7 @@ if(!bDstFileFreshlyCreated) { // if destination file was opened (as opposed to newly created) - eResult = TruncateFileFB(spFeedbackHandler, spFileDst, fsMoveTo, pData->pathDstFile, bSkip); + eResult = rFileFBWrapper.TruncateFileFB(spFeedbackHandler, spFileDst, fsMoveTo, pData->pathDstFile, bSkip); if(eResult != TSubTaskBase::eSubResult_Continue) return eResult; else if(bSkip) @@ -709,74 +718,7 @@ return false; // buffer did not need adjusting } - TSubTaskBase::ESubOperationResult TSubTaskCopyMove::OpenSourceFileFB(const IFeedbackHandlerPtr& spFeedbackHandler, const IFilesystemFilePtr& fileSrc) - { - icpf::log_file& rLog = GetContext().GetLog(); - - bool bRetry = false; - - fileSrc->Close(); - - do - { - bRetry = false; - - DWORD dwLastError = ERROR_SUCCESS; - - try - { - fileSrc->OpenExistingForReading(); - - return TSubTaskBase::eSubResult_Continue; - } - catch (const TFileException& e) - { - dwLastError = e.GetNativeError(); - } - - EFeedbackResult frResult = spFeedbackHandler->FileError(fileSrc->GetFilePath().ToWString(), TString(), EFileError::eCreateError, dwLastError); - switch(frResult) - { - case EFeedbackResult::eResult_Skip: - break; // will return INVALID_HANDLE_VALUE - - 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"), fileSrc->GetFilePath().ToString()); - rLog.loge(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"), fileSrc->GetFilePath().ToString()); - rLog.loge(strFormat.c_str()); - - bRetry = true; - break; - } - - default: - BOOST_ASSERT(FALSE); // unknown result - THROW_CORE_EXCEPTION(eErr_UnhandledCase); - } - } - while(bRetry); - - return TSubTaskBase::eSubResult_Continue; - } - - TSubTaskBase::ESubOperationResult TSubTaskCopyMove::OpenDestinationFileFB(const IFeedbackHandlerPtr& spFeedbackHandler, const IFilesystemFilePtr& fileDst, + TSubTaskBase::ESubOperationResult TSubTaskCopyMove::OpenDestinationFileFB(TFilesystemFileFeedbackWrapper& rFileFBWrapper, const IFeedbackHandlerPtr& spFeedbackHandler, const IFilesystemFilePtr& fileDst, const TFileInfoPtr& spSrcFileInfo, unsigned long long& ullSeekTo, bool& bFreshlyCreated) { icpf::log_file& rLog = GetContext().GetLog(); @@ -808,7 +750,7 @@ bFreshlyCreated = false; // pass it to the specialized method - TSubTaskBase::ESubOperationResult eResult = OpenExistingDestinationFileFB(spFeedbackHandler, fileDst); + TSubTaskBase::ESubOperationResult eResult = rFileFBWrapper.OpenExistingDestinationFileFB(spFeedbackHandler, fileDst); if(eResult != TSubTaskBase::eSubResult_Continue) return eResult; else if(!fileDst->IsOpen()) @@ -898,181 +840,6 @@ return TSubTaskBase::eSubResult_Continue; } - TSubTaskBase::ESubOperationResult TSubTaskCopyMove::OpenExistingDestinationFileFB(const IFeedbackHandlerPtr& spFeedbackHandler, const IFilesystemFilePtr& fileDst) - { - icpf::log_file& rLog = GetContext().GetLog(); - - bool bRetry = false; - - fileDst->Close(); - - do - { - bRetry = false; - - DWORD dwLastError = ERROR_SUCCESS; - try - { - fileDst->OpenExistingForWriting(); - return TSubTaskBase::eSubResult_Continue; - } - catch (const TFileException& e) - { - dwLastError = e.GetNativeError(); - } - - EFeedbackResult frResult = spFeedbackHandler->FileError(fileDst->GetFilePath().ToWString(), TString(), EFileError::eCreateError, dwLastError); - switch (frResult) - { - 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()); - rLog.loge(strFormat.c_str()); - - 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()); - rLog.loge(strFormat.c_str()); - - return TSubTaskBase::eSubResult_CancelRequest; - } - - case EFeedbackResult::eResult_Skip: - break; // will return invalid handle value - - case EFeedbackResult::eResult_Pause: - return TSubTaskBase::eSubResult_PauseRequest; - - default: - BOOST_ASSERT(FALSE); // unknown result - THROW_CORE_EXCEPTION(eErr_UnhandledCase); - } - } - while(bRetry); - - return TSubTaskBase::eSubResult_Continue; - } - - TSubTaskBase::ESubOperationResult TSubTaskCopyMove::TruncateFileFB(const IFeedbackHandlerPtr& spFeedbackHandler, const IFilesystemFilePtr& spFile, file_size_t fsNewSize, - const TSmartPath& pathFile, bool& bSkip) - { - icpf::log_file& rLog = GetContext().GetLog(); - - bSkip = false; - - bool bRetry = false; - do - { - DWORD dwLastError = ERROR_SUCCESS; - - try - { - spFile->Truncate(fsNewSize); - return TSubTaskBase::eSubResult_Continue; - } - catch (const TFileException& e) - { - dwLastError = e.GetNativeError(); - } - - TString strFormat = _T("Error %errno while truncating file %path to 0"); - strFormat.Replace(_t("%errno"), boost::lexical_cast(dwLastError).c_str()); - strFormat.Replace(_t("%path"), pathFile.ToString()); - rLog.loge(strFormat.c_str()); - - EFeedbackResult frResult = spFeedbackHandler->FileError(pathFile.ToWString(), TString(), EFileError::eResizeError, dwLastError); - switch(frResult) - { - case EFeedbackResult::eResult_Cancel: - return TSubTaskBase::eSubResult_CancelRequest; - - case EFeedbackResult::eResult_Retry: - bRetry = true; - break; - - case EFeedbackResult::eResult_Pause: - return TSubTaskBase::eSubResult_PauseRequest; - - case EFeedbackResult::eResult_Skip: - bSkip = true; - return TSubTaskBase::eSubResult_Continue; - - default: - BOOST_ASSERT(FALSE); // unknown result - THROW_CORE_EXCEPTION(eErr_UnhandledCase); - } - } - while(bRetry); - - return TSubTaskBase::eSubResult_Continue; - } - - TSubTaskBase::ESubOperationResult TSubTaskCopyMove::ReadFileFB(const IFeedbackHandlerPtr& spFeedbackHandler, const IFilesystemFilePtr& spFile, - TOverlappedDataBuffer& rBuffer, const TSmartPath& pathFile, bool& bSkip) - { - icpf::log_file& rLog = GetContext().GetLog(); - - bSkip = false; - bool bRetry = false; - do - { - bRetry = false; - - DWORD dwLastError = ERROR_SUCCESS; - - try - { - spFile->ReadFile(rBuffer); - return TSubTaskBase::eSubResult_Continue; - } - catch (const TFileException& e) - { - dwLastError = e.GetNativeError(); - } - - TString strFormat = _T("Error %errno while requesting read of %count bytes from source file %path (CustomCopyFileFB)"); - strFormat.Replace(_t("%errno"), boost::lexical_cast(dwLastError).c_str()); - strFormat.Replace(_t("%count"), boost::lexical_cast(rBuffer.GetRequestedDataSize()).c_str()); - strFormat.Replace(_t("%path"), pathFile.ToString()); - rLog.loge(strFormat.c_str()); - - EFeedbackResult frResult = spFeedbackHandler->FileError(pathFile.ToWString(), TString(), EFileError::eReadError, dwLastError); - switch(frResult) - { - case EFeedbackResult::eResult_Cancel: - return TSubTaskBase::eSubResult_CancelRequest; - - case EFeedbackResult::eResult_Retry: - bRetry = true; - break; - - case EFeedbackResult::eResult_Pause: - return TSubTaskBase::eSubResult_PauseRequest; - - case EFeedbackResult::eResult_Skip: - bSkip = true; - return TSubTaskBase::eSubResult_Continue; - - default: - BOOST_ASSERT(FALSE); // unknown result - THROW_CORE_EXCEPTION(eErr_UnhandledCase); - } - } - while(bRetry); - - return TSubTaskBase::eSubResult_Continue; - } - TSubTaskBase::ESubOperationResult TSubTaskCopyMove::HandleReadError(const IFeedbackHandlerPtr& spFeedbackHandler, TOverlappedDataBuffer& rBuffer, const TSmartPath& pathFile, @@ -1112,63 +879,6 @@ } } - TSubTaskBase::ESubOperationResult TSubTaskCopyMove::WriteFileFB(const IFeedbackHandlerPtr& spFeedbackHandler, const IFilesystemFilePtr& spFile, - TOverlappedDataBuffer& rBuffer, const TSmartPath& pathFile, bool& bSkip) - { - icpf::log_file& rLog = GetContext().GetLog(); - - bSkip = false; - - bool bRetry = false; - do - { - bRetry = false; - - DWORD dwLastError = ERROR_SUCCESS; - - try - { - spFile->WriteFile(rBuffer); - return TSubTaskBase::eSubResult_Continue; - } - catch (const TFileException& e) - { - dwLastError = e.GetNativeError(); - } - - TString strFormat = _T("Error %errno while trying to write %count bytes to destination file %path (CustomCopyFileFB)"); - strFormat.Replace(_t("%errno"), boost::lexical_cast(dwLastError).c_str()); - strFormat.Replace(_t("%count"), boost::lexical_cast(rBuffer.GetBytesTransferred()).c_str()); - strFormat.Replace(_t("%path"), pathFile.ToString()); - rLog.loge(strFormat.c_str()); - - EFeedbackResult frResult = spFeedbackHandler->FileError(pathFile.ToWString(), TString(), EFileError::eWriteError, dwLastError); - switch(frResult) - { - case EFeedbackResult::eResult_Cancel: - return TSubTaskBase::eSubResult_CancelRequest; - - case EFeedbackResult::eResult_Retry: - bRetry = true; - break; - - case EFeedbackResult::eResult_Pause: - return TSubTaskBase::eSubResult_PauseRequest; - - case EFeedbackResult::eResult_Skip: - bSkip = true; - return TSubTaskBase::eSubResult_Continue; - - default: - BOOST_ASSERT(FALSE); // unknown result - THROW_CORE_EXCEPTION(eErr_UnhandledCase); - } - } - while(bRetry); - - return TSubTaskBase::eSubResult_Continue; - } - TSubTaskBase::ESubOperationResult TSubTaskCopyMove::HandleWriteError(const IFeedbackHandlerPtr& spFeedbackHandler, TOverlappedDataBuffer& rBuffer, const TSmartPath& pathFile, @@ -1208,218 +918,6 @@ } } - TSubTaskBase::ESubOperationResult TSubTaskCopyMove::FinalizeFileFB(const IFeedbackHandlerPtr& spFeedbackHandler, const IFilesystemFilePtr& spFile, - TOverlappedDataBuffer& rBuffer, const TSmartPath& pathFile, bool& bSkip) - { - icpf::log_file& rLog = GetContext().GetLog(); - - bSkip = false; - - bool bRetry = false; - do - { - bRetry = false; - - DWORD dwLastError = ERROR_SUCCESS; - - try - { - spFile->FinalizeFile(rBuffer); - return TSubTaskBase::eSubResult_Continue; - } - catch (const TFileException& e) - { - dwLastError = e.GetNativeError(); - } - - TString strFormat = _T("Error %errno while trying to finalize file %path (CustomCopyFileFB)"); - strFormat.Replace(_t("%errno"), boost::lexical_cast(dwLastError).c_str()); - strFormat.Replace(_t("%path"), pathFile.ToString()); - rLog.loge(strFormat.c_str()); - - EFeedbackResult frResult = spFeedbackHandler->FileError(pathFile.ToWString(), TString(), EFileError::eFinalizeError, dwLastError); - switch (frResult) - { - case EFeedbackResult::eResult_Cancel: - return TSubTaskBase::eSubResult_CancelRequest; - - case EFeedbackResult::eResult_Retry: - bRetry = true; - break; - - case EFeedbackResult::eResult_Pause: - return TSubTaskBase::eSubResult_PauseRequest; - - case EFeedbackResult::eResult_Skip: - bSkip = true; - return TSubTaskBase::eSubResult_Continue; - - default: - BOOST_ASSERT(FALSE); // unknown result - THROW_CORE_EXCEPTION(eErr_UnhandledCase); - } - } while (bRetry); - - return TSubTaskBase::eSubResult_Continue; - } - - TSubTaskBase::ESubOperationResult TSubTaskCopyMove::CreateDirectoryFB(const IFeedbackHandlerPtr& spFeedbackHandler, const TSmartPath& pathDirectory) - { - icpf::log_file& rLog = GetContext().GetLog(); - IFilesystemPtr spFilesystem = GetContext().GetLocalFilesystem(); - - bool bRetry = false; - do - { - bRetry = false; - - DWORD dwLastError = ERROR_SUCCESS; - try - { - spFilesystem->CreateDirectory(pathDirectory, false); - return TSubTaskBase::eSubResult_Continue; - } - catch (const TFileException& e) - { - dwLastError = e.GetNativeError(); - } - - if (dwLastError == ERROR_ALREADY_EXISTS) - return TSubTaskBase::eSubResult_Continue; - - // log - TString strFormat; - strFormat = _T("Error %errno while calling CreateDirectory %path (ProcessFiles)"); - strFormat.Replace(_T("%errno"), boost::lexical_cast(dwLastError).c_str()); - strFormat.Replace(_T("%path"), pathDirectory.ToString()); - rLog.loge(strFormat.c_str()); - - EFeedbackResult frResult = spFeedbackHandler->FileError(pathDirectory.ToWString(), TString(), EFileError::eCreateError, dwLastError); - switch(frResult) - { - case EFeedbackResult::eResult_Cancel: - return TSubTaskBase::eSubResult_CancelRequest; - - case EFeedbackResult::eResult_Retry: - bRetry = true; - break; - - case EFeedbackResult::eResult_Pause: - return TSubTaskBase::eSubResult_PauseRequest; - - case EFeedbackResult::eResult_Skip: - break; // just do nothing - - default: - BOOST_ASSERT(FALSE); // unknown result - THROW_CORE_EXCEPTION(eErr_UnhandledCase); - } - } - while (bRetry); - - return TSubTaskBase::eSubResult_Continue; - } - - TSubTaskBase::ESubOperationResult TSubTaskCopyMove::CheckForFreeSpaceFB(const IFeedbackHandlerPtr& spFeedbackHandler) - { - icpf::log_file& rLog = GetContext().GetLog(); - IFilesystemPtr spFilesystem = GetContext().GetLocalFilesystem(); - TFileInfoArray& rFilesCache = GetContext().GetFilesCache(); - TBasePathDataContainerPtr spSrcPaths = GetContext().GetBasePaths(); - TSmartPath pathDestination = GetContext().GetDestinationPath(); - - ull_t ullNeededSize = 0, ullAvailableSize = 0; - bool bRetry = false; - - do - { - bRetry = false; - - rLog.logi(_T("Checking for free space on destination disk...")); - - // #nicetohave it'd be nice to round up to take cluster size into consideration - ullNeededSize = rFilesCache.CalculateTotalSize() - rFilesCache.CalculatePartialSize(m_tSubTaskStats.GetCurrentIndex()); - - // get free space - DWORD dwLastError = ERROR_SUCCESS; - bool bCheckFailed = false; - try - { - spFilesystem->GetDynamicFreeSpace(pathDestination, ullAvailableSize); - } - catch (const TFileException& e) - { - dwLastError = e.GetNativeError(); - bCheckFailed = true; - } - - if(bCheckFailed) - { - TString strFormat; - strFormat = _T("Error %errno while checking free space at %path"); - strFormat.Replace(_T("%errno"), boost::lexical_cast(dwLastError).c_str()); - strFormat.Replace(_T("%path"), pathDestination.ToString()); - rLog.loge(strFormat.c_str()); - - EFeedbackResult frResult = spFeedbackHandler->FileError(pathDestination.ToWString(), TString(), EFileError::eCheckForFreeSpace, dwLastError); - switch (frResult) - { - case EFeedbackResult::eResult_Cancel: - return TSubTaskBase::eSubResult_CancelRequest; - - case EFeedbackResult::eResult_Retry: - bRetry = true; - continue; - - case EFeedbackResult::eResult_Pause: - return TSubTaskBase::eSubResult_PauseRequest; - - case EFeedbackResult::eResult_Skip: - return TSubTaskBase::eSubResult_Continue; - - default: - BOOST_ASSERT(FALSE); // unknown result - THROW_CORE_EXCEPTION(eErr_UnhandledCase); - } - } - - if(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()); - rLog.logw(strFormat.c_str()); - - if(!spSrcPaths->IsEmpty()) - { - EFeedbackResult frResult = spFeedbackHandler->NotEnoughSpace(spSrcPaths->GetAt(0)->GetSrcPath().ToWString(), pathDestination.ToWString(), ullNeededSize); - switch(frResult) - { - case EFeedbackResult::eResult_Cancel: - rLog.logi(_T("Cancel request while checking for free space on disk.")); - return TSubTaskBase::eSubResult_CancelRequest; - - case EFeedbackResult::eResult_Retry: - rLog.logi(_T("Retrying to read drive's free space...")); - bRetry = true; - break; - - case EFeedbackResult::eResult_Ignore: - rLog.logi(_T("Ignored warning about not enough place on disk to copy data.")); - return TSubTaskBase::eSubResult_Continue; - - default: - BOOST_ASSERT(FALSE); // unknown result - THROW_CORE_EXCEPTION(eErr_UnhandledCase); - } - } - } - } - while(bRetry); - - return TSubTaskBase::eSubResult_Continue; - } - void TSubTaskCopyMove::Store(const ISerializerPtr& spSerializer) const { ISerializerContainerPtr spContainer = spSerializer->GetContainer(_T("subtask_copymove")); Index: src/libchcore/TSubTaskCopyMove.h =================================================================== diff -u -rdb818324a61602e118506ca8b3973e44d997c8de -r09d769045d1d5c45d8df16d209c754b872348c26 --- src/libchcore/TSubTaskCopyMove.h (.../TSubTaskCopyMove.h) (revision db818324a61602e118506ca8b3973e44d997c8de) +++ src/libchcore/TSubTaskCopyMove.h (.../TSubTaskCopyMove.h) (revision 09d769045d1d5c45d8df16d209c754b872348c26) @@ -40,6 +40,7 @@ class TBufferSizes; class TOverlappedDataBufferQueue; class TOverlappedDataBuffer; + class TFilesystemFileFeedbackWrapper; class LIBCHCORE_API TSubTaskCopyMove : public TSubTaskBase { @@ -64,34 +65,17 @@ ESubOperationResult CustomCopyFileFB(const IFeedbackHandlerPtr& spFeedbackHandler, CUSTOM_COPY_PARAMS* pData); - ESubOperationResult OpenSrcAndDstFilesFB(const IFeedbackHandlerPtr& spFeedbackHandler, CUSTOM_COPY_PARAMS* pData, + ESubOperationResult OpenSrcAndDstFilesFB(TFilesystemFileFeedbackWrapper& rFileFBWrapper, const IFeedbackHandlerPtr& spFeedbackHandler, CUSTOM_COPY_PARAMS* pData, const IFilesystemFilePtr& spFileSrc, const IFilesystemFilePtr& spFileDst, bool& bSkip); - ESubOperationResult OpenSourceFileFB(const IFeedbackHandlerPtr& spFeedbackHandler, const IFilesystemFilePtr& fileSrc); - ESubOperationResult OpenDestinationFileFB(const IFeedbackHandlerPtr& spFeedbackHandler, const IFilesystemFilePtr& fileDst, const TFileInfoPtr& spSrcFileInfo, + ESubOperationResult OpenDestinationFileFB(TFilesystemFileFeedbackWrapper& rFileFBWrapper, const IFeedbackHandlerPtr& spFeedbackHandler, const IFilesystemFilePtr& fileDst, const TFileInfoPtr& spSrcFileInfo, unsigned long long& ullSeekTo, bool& bFreshlyCreated); - ESubOperationResult OpenExistingDestinationFileFB(const IFeedbackHandlerPtr& spFeedbackHandler, const IFilesystemFilePtr& fileDst); - ESubOperationResult TruncateFileFB(const IFeedbackHandlerPtr& spFeedbackHandler, const IFilesystemFilePtr& file, file_size_t fsNewSize, - const TSmartPath& pathFile, bool& bSkip); - - ESubOperationResult ReadFileFB(const IFeedbackHandlerPtr& spFeedbackHandler, const IFilesystemFilePtr& file, - TOverlappedDataBuffer& rBuffer, const TSmartPath& pathFile, bool& bSkip); ESubOperationResult HandleReadError(const IFeedbackHandlerPtr& spFeedbackHandler, TOverlappedDataBuffer& rBuffer, const TSmartPath& pathFile, bool& bSkip); - - ESubOperationResult WriteFileFB(const IFeedbackHandlerPtr& spFeedbackHandler, const IFilesystemFilePtr& file, - TOverlappedDataBuffer& rBuffer, const TSmartPath& pathFile, bool& bSkip); ESubOperationResult HandleWriteError(const IFeedbackHandlerPtr& spFeedbackHandler, TOverlappedDataBuffer& rBuffer, const TSmartPath& pathFile, bool& bSkip); - ESubOperationResult FinalizeFileFB(const IFeedbackHandlerPtr& spFeedbackHandler, const IFilesystemFilePtr& file, - TOverlappedDataBuffer& rBuffer, const TSmartPath& pathFile, bool& bSkip); - - ESubOperationResult CreateDirectoryFB(const IFeedbackHandlerPtr& spFeedbackHandler, const TSmartPath& pathDirectory); - - ESubOperationResult CheckForFreeSpaceFB(const IFeedbackHandlerPtr& spFeedbackHandler); - void AdjustProcessedSize(file_size_t fsWritten, const TFileInfoPtr& spSrcFileInfo, const IFilesystemFilePtr& spSrcFile); void AdjustFinalSize(const TFileInfoPtr& spSrcFileInfo, const IFilesystemFilePtr& spSrcFile); void AdjustProcessedSizeForSkip(const TFileInfoPtr& spSrcFileInfo); Index: src/libchcore/libchcore.vc140.vcxproj =================================================================== diff -u -r27a43e40952cf2f3e0bb0e608a8f3142042ceb46 -r09d769045d1d5c45d8df16d209c754b872348c26 --- src/libchcore/libchcore.vc140.vcxproj (.../libchcore.vc140.vcxproj) (revision 27a43e40952cf2f3e0bb0e608a8f3142042ceb46) +++ src/libchcore/libchcore.vc140.vcxproj (.../libchcore.vc140.vcxproj) (revision 09d769045d1d5c45d8df16d209c754b872348c26) @@ -532,9 +532,11 @@ + + @@ -764,10 +766,12 @@ + + Index: src/libchcore/libchcore.vc140.vcxproj.filters =================================================================== diff -u -r27a43e40952cf2f3e0bb0e608a8f3142042ceb46 -r09d769045d1d5c45d8df16d209c754b872348c26 --- src/libchcore/libchcore.vc140.vcxproj.filters (.../libchcore.vc140.vcxproj.filters) (revision 27a43e40952cf2f3e0bb0e608a8f3142042ceb46) +++ src/libchcore/libchcore.vc140.vcxproj.filters (.../libchcore.vc140.vcxproj.filters) (revision 09d769045d1d5c45d8df16d209c754b872348c26) @@ -467,6 +467,12 @@ Source Files\Filesystems\Exceptions + + Source Files\SubTasks + + + Source Files\SubTasks + @@ -853,5 +859,11 @@ Source Files\Filesystems\Exceptions + + Source Files\SubTasks + + + Source Files\SubTasks + \ No newline at end of file