Index: src/libchcore/TFilesystemFeedbackWrapper.cpp =================================================================== diff -u -N -rfc42a6399299d4b90268695740a9e6e35ab25b05 -ra4635addad389b9e117679437a3e1b64a739ea96 --- src/libchcore/TFilesystemFeedbackWrapper.cpp (.../TFilesystemFeedbackWrapper.cpp) (revision fc42a6399299d4b90268695740a9e6e35ab25b05) +++ src/libchcore/TFilesystemFeedbackWrapper.cpp (.../TFilesystemFeedbackWrapper.cpp) (revision a4635addad389b9e117679437a3e1b64a739ea96) @@ -1,426 +1,426 @@ -// ============================================================================ -// 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" -#include "TFileInfo.h" -#include "TWorkerThreadController.h" - -namespace chcore -{ - TFilesystemFeedbackWrapper::TFilesystemFeedbackWrapper(const IFeedbackHandlerPtr& spFeedbackHandler, const IFilesystemPtr& spFilesystem, const logger::TLogFileDataPtr& spLogFileData, TWorkerThreadController& rThreadController) : - m_spFeedbackHandler(spFeedbackHandler), - m_spFilesystem(spFilesystem), - m_spLog(logger::MakeLogger(spLogFileData, L"Filesystem")), - m_rThreadController(rThreadController) - { - if (!spFilesystem) - throw TCoreException(eErr_InvalidArgument, L"Filesystem not provided", LOCATION); - } - - TSubTaskBase::ESubOperationResult TFilesystemFeedbackWrapper::CreateDirectoryFB(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()); - LOG_ERROR(m_spLog) << strFormat.c_str(); - - TFeedbackResult frResult = m_spFeedbackHandler->FileError(pathDirectory.ToWString(), TString(), EFileError::eCreateError, dwLastError); - switch (frResult.GetResult()) - { - case eResult_Cancel: - return TSubTaskBase::eSubResult_CancelRequest; - - case eResult_Retry: - bRetry = true; - break; - - case eResult_Pause: - return TSubTaskBase::eSubResult_PauseRequest; - - case eResult_Skip: - return TSubTaskBase::eSubResult_Continue; - - 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; - } - - 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, ullTotal = 0; - TFeedbackResult frResult(eResult_Unknown, false); - bool bRetry = false; - - do - { - bRetry = false; - - LOG_INFO(m_spLog) << _T("Checking for free space on destination disk..."); - - // get free space - DWORD dwLastError = ERROR_SUCCESS; - bool bCheckFailed = false; - try - { - m_spFilesystem->GetDynamicFreeSpace(pathDestination, ullAvailableSize, ullTotal); - } - 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()); - LOG_ERROR(m_spLog) << strFormat.c_str(); - - frResult = m_spFeedbackHandler->FileError(pathDestination.ToWString(), TString(), EFileError::eCheckForFreeSpace, dwLastError); - switch (frResult.GetResult()) - { - case eResult_Cancel: - return TSubTaskBase::eSubResult_CancelRequest; - - case eResult_Retry: - bRetry = true; - break; - - case eResult_Pause: - return TSubTaskBase::eSubResult_PauseRequest; - - case eResult_Skip: - return TSubTaskBase::eSubResult_Continue; - - default: - BOOST_ASSERT(FALSE); // unknown result - throw TCoreException(eErr_UnhandledCase, L"Feedback result unknown", LOCATION); - } - } - - 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()); - LOG_WARNING(m_spLog) << strFormat.c_str(); - - frResult = m_spFeedbackHandler->NotEnoughSpace(pathFirstSrc.ToWString(), pathDestination.ToWString(), ullNeededSize); - switch (frResult.GetResult()) - { - case eResult_Cancel: - LOG_INFO(m_spLog) << _T("Cancel request while checking for free space on disk."); - return TSubTaskBase::eSubResult_CancelRequest; - - case eResult_Retry: - LOG_INFO(m_spLog) << _T("Retrying to read drive's free space..."); - bRetry = true; - break; - - case eResult_Ignore: - LOG_INFO(m_spLog) << _T("Ignored warning about not enough place on disk to copy data."); - return TSubTaskBase::eSubResult_Continue; - - default: - BOOST_ASSERT(FALSE); // unknown result - throw TCoreException(eErr_UnhandledCase, L"Feedback result unknown", LOCATION); - } - } - - if(bRetry && WasKillRequested(frResult)) - return TSubTaskBase::eSubResult_KillRequest; - } - while (bRetry); - - return TSubTaskBase::eSubResult_Continue; - } - - TSubTaskBase::ESubOperationResult TFilesystemFeedbackWrapper::RemoveDirectoryFB(const TFileInfoPtr& spFileInfo, bool bProtectReadOnlyFiles) - { - bool bRetry = false; - do - { - bRetry = false; - DWORD dwLastError = ERROR_SUCCESS; - - try - { - DWORD dwAttributes = spFileInfo->GetAttributes(); - if((dwAttributes & FILE_ATTRIBUTE_READONLY) && !bProtectReadOnlyFiles) - m_spFilesystem->SetAttributes(spFileInfo->GetFullFilePath(), dwAttributes & ~FILE_ATTRIBUTE_READONLY); - - m_spFilesystem->RemoveDirectory(spFileInfo->GetFullFilePath()); - return TSubTaskBase::eSubResult_Continue; - } - catch (const TFileException& e) - { - dwLastError = e.GetNativeError(); - } - - if(dwLastError == ERROR_PATH_NOT_FOUND || dwLastError == ERROR_FILE_NOT_FOUND) - return TSubTaskBase::eSubResult_Continue; - - // log - TString strFormat = _T("Error #%errno while deleting folder %path"); - strFormat.Replace(_T("%errno"), boost::lexical_cast(dwLastError).c_str()); - strFormat.Replace(_T("%path"), spFileInfo->GetFullFilePath().ToString()); - LOG_ERROR(m_spLog) << strFormat.c_str(); - - TFeedbackResult frResult = m_spFeedbackHandler->FileError(spFileInfo->GetFullFilePath().ToWString(), TString(), EFileError::eDeleteError, dwLastError); - switch (frResult.GetResult()) - { - case eResult_Cancel: - LOG_INFO(m_spLog) << _T("Cancel request while deleting file."); - return TSubTaskBase::eSubResult_CancelRequest; - - case eResult_Retry: - bRetry = true; - break; // no fcIndex bump, since we are trying again - - case eResult_Pause: - return TSubTaskBase::eSubResult_PauseRequest; - - case eResult_Skip: - return TSubTaskBase::eSubResult_Continue; // just do nothing - - 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 TFilesystemFeedbackWrapper::DeleteFileFB(const TFileInfoPtr& spFileInfo, bool bProtectReadOnlyFiles) - { - bool bRetry = false; - do - { - bRetry = false; - - DWORD dwLastError = ERROR_SUCCESS; - try - { - DWORD dwAttributes = spFileInfo->GetAttributes(); - if((dwAttributes & FILE_ATTRIBUTE_READONLY) && !bProtectReadOnlyFiles) - m_spFilesystem->SetAttributes(spFileInfo->GetFullFilePath(), dwAttributes & ~FILE_ATTRIBUTE_READONLY); - - m_spFilesystem->DeleteFile(spFileInfo->GetFullFilePath()); - return TSubTaskBase::eSubResult_Continue; - } - catch (const TFileException& e) - { - dwLastError = e.GetNativeError(); - } - - if (dwLastError == ERROR_PATH_NOT_FOUND || dwLastError == ERROR_FILE_NOT_FOUND) - return TSubTaskBase::eSubResult_Continue; - - // log - TString strFormat = _T("Error #%errno while deleting file %path"); - strFormat.Replace(_T("%errno"), boost::lexical_cast(dwLastError).c_str()); - strFormat.Replace(_T("%path"), spFileInfo->GetFullFilePath().ToString()); - LOG_ERROR(m_spLog) << strFormat.c_str(); - - TFeedbackResult frResult = m_spFeedbackHandler->FileError(spFileInfo->GetFullFilePath().ToWString(), TString(), EFileError::eDeleteError, dwLastError); - switch (frResult.GetResult()) - { - case eResult_Cancel: - LOG_INFO(m_spLog) << _T("Cancel request while deleting file."); - return TSubTaskBase::eSubResult_CancelRequest; - - case eResult_Retry: - bRetry = true; - break; - - case eResult_Pause: - return TSubTaskBase::eSubResult_PauseRequest; - - case eResult_Skip: - return TSubTaskBase::eSubResult_Continue; // just do nothing - - 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 TFilesystemFeedbackWrapper::FastMoveFB(const TFileInfoPtr& spFileInfo, const TSmartPath& pathDestination, const TBasePathDataPtr& spBasePath) - { - bool bRetry = false; - do - { - bRetry = false; - - TSmartPath pathSrc = spBasePath->GetSrcPath(); - - DWORD dwLastError = ERROR_SUCCESS; - try - { - m_spFilesystem->FastMove(pathSrc, pathDestination); - spBasePath->SetSkipFurtherProcessing(true); // mark that this path should not be processed any further - return TSubTaskBase::eSubResult_Continue; - } - catch (const TFileException& e) - { - dwLastError = e.GetNativeError(); - } - - // check if this is one of the errors, that will just cause fast move to skip - if (dwLastError == ERROR_ACCESS_DENIED || dwLastError == ERROR_ALREADY_EXISTS || dwLastError == ERROR_NOT_SAME_DEVICE) - { - return TSubTaskBase::eSubResult_Continue; - } - - //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()); - LOG_ERROR(m_spLog) << strFormat.c_str(); - - TFeedbackResult frResult = m_spFeedbackHandler->FileError(pathSrc.ToWString(), pathDestination.ToWString(), EFileError::eFastMoveError, dwLastError); - switch (frResult.GetResult()) - { - case eResult_Cancel: - return TSubTaskBase::eSubResult_CancelRequest; - - case eResult_Retry: - bRetry = true; - break; - - case eResult_Pause: - return TSubTaskBase::eSubResult_PauseRequest; - - case eResult_Skip: - return TSubTaskBase::eSubResult_SkipFile; - - 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 TFilesystemFeedbackWrapper::GetFileInfoFB(const TSmartPath& pathCurrent, TFileInfoPtr& spFileInfo, const TBasePathDataPtr& spBasePath) - { - bool bRetry = false; - do - { - bRetry = false; - - // read attributes of src file/folder - DWORD dwLastError = ERROR_SUCCESS; - try - { - m_spFilesystem->GetFileInfo(pathCurrent, spFileInfo, spBasePath); - return TSubTaskBase::eSubResult_Continue; - } - catch (const TFileException& e) - { - dwLastError = e.GetNativeError(); - } - - TFeedbackResult frResult = m_spFeedbackHandler->FileError(pathCurrent.ToWString(), TString(), EFileError::eRetrieveFileInfo, dwLastError); - switch (frResult.GetResult()) - { - case eResult_Cancel: - return TSubTaskBase::eSubResult_CancelRequest; - - case eResult_Retry: - bRetry = true; - break; - - case eResult_Pause: - return TSubTaskBase::eSubResult_PauseRequest; - - case eResult_Skip: - return TSubTaskBase::eSubResult_SkipFile; - - 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; - } -} +// ============================================================================ +// 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" +#include "TFileInfo.h" +#include "TWorkerThreadController.h" + +namespace chcore +{ + TFilesystemFeedbackWrapper::TFilesystemFeedbackWrapper(const IFeedbackHandlerPtr& spFeedbackHandler, const IFilesystemPtr& spFilesystem, const logger::TLogFileDataPtr& spLogFileData, TWorkerThreadController& rThreadController) : + m_spFeedbackHandler(spFeedbackHandler), + m_spFilesystem(spFilesystem), + m_spLog(logger::MakeLogger(spLogFileData, L"Filesystem")), + m_rThreadController(rThreadController) + { + if (!spFilesystem) + throw TCoreException(eErr_InvalidArgument, L"Filesystem not provided", LOCATION); + } + + TSubTaskBase::ESubOperationResult TFilesystemFeedbackWrapper::CreateDirectoryFB(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()); + LOG_ERROR(m_spLog) << strFormat.c_str(); + + TFeedbackResult frResult = m_spFeedbackHandler->FileError(pathDirectory.ToWString(), TString(), EFileError::eCreateError, dwLastError); + switch (frResult.GetResult()) + { + case eResult_Cancel: + return TSubTaskBase::eSubResult_CancelRequest; + + case eResult_Retry: + bRetry = true; + break; + + case eResult_Pause: + return TSubTaskBase::eSubResult_PauseRequest; + + case eResult_Skip: + return TSubTaskBase::eSubResult_Continue; + + 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; + } + + 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, ullTotal = 0; + TFeedbackResult frResult(eResult_Unknown, false); + bool bRetry = false; + + do + { + bRetry = false; + + LOG_INFO(m_spLog) << _T("Checking for free space on destination disk..."); + + // get free space + DWORD dwLastError = ERROR_SUCCESS; + bool bCheckFailed = false; + try + { + m_spFilesystem->GetDynamicFreeSpace(pathDestination, ullAvailableSize, ullTotal); + } + 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()); + LOG_ERROR(m_spLog) << strFormat.c_str(); + + frResult = m_spFeedbackHandler->FileError(pathDestination.ToWString(), TString(), EFileError::eCheckForFreeSpace, dwLastError); + switch (frResult.GetResult()) + { + case eResult_Cancel: + return TSubTaskBase::eSubResult_CancelRequest; + + case eResult_Retry: + bRetry = true; + break; + + case eResult_Pause: + return TSubTaskBase::eSubResult_PauseRequest; + + case eResult_Skip: + return TSubTaskBase::eSubResult_Continue; + + default: + BOOST_ASSERT(FALSE); // unknown result + throw TCoreException(eErr_UnhandledCase, L"Feedback result unknown", LOCATION); + } + } + + 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()); + LOG_WARNING(m_spLog) << strFormat.c_str(); + + frResult = m_spFeedbackHandler->NotEnoughSpace(pathFirstSrc.ToWString(), pathDestination.ToWString(), ullNeededSize); + switch (frResult.GetResult()) + { + case eResult_Cancel: + LOG_INFO(m_spLog) << _T("Cancel request while checking for free space on disk."); + return TSubTaskBase::eSubResult_CancelRequest; + + case eResult_Retry: + LOG_INFO(m_spLog) << _T("Retrying to read drive's free space..."); + bRetry = true; + break; + + case eResult_Ignore: + LOG_INFO(m_spLog) << _T("Ignored warning about not enough place on disk to copy data."); + return TSubTaskBase::eSubResult_Continue; + + default: + BOOST_ASSERT(FALSE); // unknown result + throw TCoreException(eErr_UnhandledCase, L"Feedback result unknown", LOCATION); + } + } + + if(bRetry && WasKillRequested(frResult)) + return TSubTaskBase::eSubResult_KillRequest; + } + while (bRetry); + + return TSubTaskBase::eSubResult_Continue; + } + + TSubTaskBase::ESubOperationResult TFilesystemFeedbackWrapper::RemoveDirectoryFB(const TFileInfoPtr& spFileInfo, bool bProtectReadOnlyFiles) + { + bool bRetry = false; + do + { + bRetry = false; + DWORD dwLastError = ERROR_SUCCESS; + + try + { + DWORD dwAttributes = spFileInfo->GetAttributes(); + if((dwAttributes & FILE_ATTRIBUTE_READONLY) && !bProtectReadOnlyFiles) + m_spFilesystem->SetAttributes(spFileInfo->GetFullFilePath(), dwAttributes & ~FILE_ATTRIBUTE_READONLY); + + m_spFilesystem->RemoveDirectory(spFileInfo->GetFullFilePath()); + return TSubTaskBase::eSubResult_Continue; + } + catch (const TFileException& e) + { + dwLastError = e.GetNativeError(); + } + + if(dwLastError == ERROR_PATH_NOT_FOUND || dwLastError == ERROR_FILE_NOT_FOUND) + return TSubTaskBase::eSubResult_Continue; + + // log + TString strFormat = _T("Error #%errno while deleting folder %path"); + strFormat.Replace(_T("%errno"), boost::lexical_cast(dwLastError).c_str()); + strFormat.Replace(_T("%path"), spFileInfo->GetFullFilePath().ToString()); + LOG_ERROR(m_spLog) << strFormat.c_str(); + + TFeedbackResult frResult = m_spFeedbackHandler->FileError(spFileInfo->GetFullFilePath().ToWString(), TString(), EFileError::eDeleteError, dwLastError); + switch (frResult.GetResult()) + { + case eResult_Cancel: + LOG_INFO(m_spLog) << _T("Cancel request while deleting file."); + return TSubTaskBase::eSubResult_CancelRequest; + + case eResult_Retry: + bRetry = true; + break; // no fcIndex bump, since we are trying again + + case eResult_Pause: + return TSubTaskBase::eSubResult_PauseRequest; + + case eResult_Skip: + return TSubTaskBase::eSubResult_Continue; // just do nothing + + 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 TFilesystemFeedbackWrapper::DeleteFileFB(const TFileInfoPtr& spFileInfo, bool bProtectReadOnlyFiles) + { + bool bRetry = false; + do + { + bRetry = false; + + DWORD dwLastError = ERROR_SUCCESS; + try + { + DWORD dwAttributes = spFileInfo->GetAttributes(); + if((dwAttributes & FILE_ATTRIBUTE_READONLY) && !bProtectReadOnlyFiles) + m_spFilesystem->SetAttributes(spFileInfo->GetFullFilePath(), dwAttributes & ~FILE_ATTRIBUTE_READONLY); + + m_spFilesystem->DeleteFile(spFileInfo->GetFullFilePath()); + return TSubTaskBase::eSubResult_Continue; + } + catch (const TFileException& e) + { + dwLastError = e.GetNativeError(); + } + + if (dwLastError == ERROR_PATH_NOT_FOUND || dwLastError == ERROR_FILE_NOT_FOUND) + return TSubTaskBase::eSubResult_Continue; + + // log + TString strFormat = _T("Error #%errno while deleting file %path"); + strFormat.Replace(_T("%errno"), boost::lexical_cast(dwLastError).c_str()); + strFormat.Replace(_T("%path"), spFileInfo->GetFullFilePath().ToString()); + LOG_ERROR(m_spLog) << strFormat.c_str(); + + TFeedbackResult frResult = m_spFeedbackHandler->FileError(spFileInfo->GetFullFilePath().ToWString(), TString(), EFileError::eDeleteError, dwLastError); + switch (frResult.GetResult()) + { + case eResult_Cancel: + LOG_INFO(m_spLog) << _T("Cancel request while deleting file."); + return TSubTaskBase::eSubResult_CancelRequest; + + case eResult_Retry: + bRetry = true; + break; + + case eResult_Pause: + return TSubTaskBase::eSubResult_PauseRequest; + + case eResult_Skip: + return TSubTaskBase::eSubResult_Continue; // just do nothing + + 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 TFilesystemFeedbackWrapper::FastMoveFB(const TFileInfoPtr& spFileInfo, const TSmartPath& pathDestination, const TBasePathDataPtr& spBasePath) + { + bool bRetry = false; + do + { + bRetry = false; + + TSmartPath pathSrc = spBasePath->GetSrcPath(); + + DWORD dwLastError = ERROR_SUCCESS; + try + { + m_spFilesystem->FastMove(pathSrc, pathDestination); + spBasePath->SetSkipFurtherProcessing(true); // mark that this path should not be processed any further + return TSubTaskBase::eSubResult_Continue; + } + catch (const TFileException& e) + { + dwLastError = e.GetNativeError(); + } + + // check if this is one of the errors, that will just cause fast move to skip + if (dwLastError == ERROR_ACCESS_DENIED || dwLastError == ERROR_ALREADY_EXISTS || dwLastError == ERROR_NOT_SAME_DEVICE) + { + return TSubTaskBase::eSubResult_Continue; + } + + //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()); + LOG_ERROR(m_spLog) << strFormat.c_str(); + + TFeedbackResult frResult = m_spFeedbackHandler->FileError(pathSrc.ToWString(), pathDestination.ToWString(), EFileError::eFastMoveError, dwLastError); + switch (frResult.GetResult()) + { + case eResult_Cancel: + return TSubTaskBase::eSubResult_CancelRequest; + + case eResult_Retry: + bRetry = true; + break; + + case eResult_Pause: + return TSubTaskBase::eSubResult_PauseRequest; + + case eResult_Skip: + return TSubTaskBase::eSubResult_SkipFile; + + 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 TFilesystemFeedbackWrapper::GetFileInfoFB(const TSmartPath& pathCurrent, TFileInfoPtr& spFileInfo, const TBasePathDataPtr& spBasePath) + { + bool bRetry = false; + do + { + bRetry = false; + + // read attributes of src file/folder + DWORD dwLastError = ERROR_SUCCESS; + try + { + m_spFilesystem->GetFileInfo(pathCurrent, spFileInfo, spBasePath); + return TSubTaskBase::eSubResult_Continue; + } + catch (const TFileException& e) + { + dwLastError = e.GetNativeError(); + } + + TFeedbackResult frResult = m_spFeedbackHandler->FileError(pathCurrent.ToWString(), TString(), EFileError::eRetrieveFileInfo, dwLastError); + switch (frResult.GetResult()) + { + case eResult_Cancel: + return TSubTaskBase::eSubResult_CancelRequest; + + case eResult_Retry: + bRetry = true; + break; + + case eResult_Pause: + return TSubTaskBase::eSubResult_PauseRequest; + + case eResult_Skip: + return TSubTaskBase::eSubResult_SkipFile; + + 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; + } +}