Index: src/ch/StatusDlg.cpp =================================================================== diff -u -N -r1d8d51e0dd4d8ebcf0bd457d01fab984585220c0 -rd88274a4bbfd4ef005d44c4d179b7596cb627486 --- src/ch/StatusDlg.cpp (.../StatusDlg.cpp) (revision 1d8d51e0dd4d8ebcf0bd457d01fab984585220c0) +++ src/ch/StatusDlg.cpp (.../StatusDlg.cpp) (revision d88274a4bbfd4ef005d44c4d179b7596cb627486) @@ -1022,6 +1022,8 @@ strStatusText += GetResManager().LoadString(IDS_STATUS_DELETING_STRING); else if(rTaskDisplayData.m_eSubOperationType == chcore::eSubOperation_Scanning) strStatusText += GetResManager().LoadString(IDS_STATUS_SEARCHING_STRING); + else if(rTaskDisplayData.m_eSubOperationType == chcore::eSubOperation_FastMove) + strStatusText += GetResManager().LoadString(IDS_STATUS_FASTMOVE_STRING); else if(rTaskDisplayData.m_eOperationType == chcore::eOperation_Copy) strStatusText += GetResManager().LoadString(IDS_STATUS_COPYING_STRING); else if(rTaskDisplayData.m_eOperationType == chcore::eOperation_Move) Index: src/ch/ch.rc =================================================================== diff -u -N -r3127f6bb39be81d3b451ffbc3d0bad7f85d4a89f -rd88274a4bbfd4ef005d44c4d179b7596cb627486 --- src/ch/ch.rc (.../ch.rc) (revision 3127f6bb39be81d3b451ffbc3d0bad7f85d4a89f) +++ src/ch/ch.rc (.../ch.rc) (revision d88274a4bbfd4ef005d44c4d179b7596cb627486) @@ -828,6 +828,7 @@ STRINGTABLE BEGIN + IDS_STATUS_FASTMOVE_STRING "Fast moving" IDS_STATUS_SEARCHING_STRING "Searching" IDS_STATUS_COPYING_STRING "Copying" IDS_STATUS_MOVING_STRING "Moving" Index: src/ch/resource.h =================================================================== diff -u -N -r3127f6bb39be81d3b451ffbc3d0bad7f85d4a89f -rd88274a4bbfd4ef005d44c4d179b7596cb627486 --- src/ch/resource.h (.../resource.h) (revision 3127f6bb39be81d3b451ffbc3d0bad7f85d4a89f) +++ src/ch/resource.h (.../resource.h) (revision d88274a4bbfd4ef005d44c4d179b7596cb627486) @@ -560,6 +560,7 @@ #define IDS_FILTERING_STRING 21550 #define IDS_CONFIRMCANCEL_STRING 21551 #define IDS_STATUS_INITIALIZING_STRING 21552 +#define IDS_STATUS_FASTMOVE_STRING 21553 #define ID_POPUP_SHOW_STATUS 32773 #define ID_POPUP_TIME_CRITICAL 32774 #define ID_POPUP_HIGHEST 32775 Index: src/libchcore/ESubTaskTypes.h =================================================================== diff -u -N -r835e0344e9677ff02eb3b539061c48c9f3a616ce -rd88274a4bbfd4ef005d44c4d179b7596cb627486 --- src/libchcore/ESubTaskTypes.h (.../ESubTaskTypes.h) (revision 835e0344e9677ff02eb3b539061c48c9f3a616ce) +++ src/libchcore/ESubTaskTypes.h (.../ESubTaskTypes.h) (revision d88274a4bbfd4ef005d44c4d179b7596cb627486) @@ -30,6 +30,7 @@ enum ESubOperationType { eSubOperation_None, + eSubOperation_FastMove, eSubOperation_Scanning, eSubOperation_Copying, eSubOperation_Deleting, Index: src/libchcore/TBasePathData.cpp =================================================================== diff -u -N -rbe30619d750d8663d54cf02e7d4bde2ed2dd8d05 -rd88274a4bbfd4ef005d44c4d179b7596cb627486 --- src/libchcore/TBasePathData.cpp (.../TBasePathData.cpp) (revision be30619d750d8663d54cf02e7d4bde2ed2dd8d05) +++ src/libchcore/TBasePathData.cpp (.../TBasePathData.cpp) (revision d88274a4bbfd4ef005d44c4d179b7596cb627486) @@ -31,12 +31,11 @@ // TBasePathData TBasePathData::TBasePathData() : - m_bMove(true) + m_bSkipFurtherProcessing(false) { } TBasePathData::TBasePathData(const TBasePathData& rEntry) : - m_bMove(rEntry.m_bMove), m_pathDst(rEntry.m_pathDst) { } @@ -54,15 +53,15 @@ void TBasePathData::Serialize(TReadBinarySerializer& rSerializer, bool bData) { if(bData) - Serializers::Serialize(rSerializer, m_bMove); + Serializers::Serialize(rSerializer, m_bSkipFurtherProcessing); else Serializers::Serialize(rSerializer, m_pathDst); } void TBasePathData::Serialize(TWriteBinarySerializer& rSerializer, bool bData) { if(bData) - Serializers::Serialize(rSerializer, m_bMove); + Serializers::Serialize(rSerializer, m_bSkipFurtherProcessing); else Serializers::Serialize(rSerializer, m_pathDst); } Index: src/libchcore/TBasePathData.h =================================================================== diff -u -N -rbe30619d750d8663d54cf02e7d4bde2ed2dd8d05 -rd88274a4bbfd4ef005d44c4d179b7596cb627486 --- src/libchcore/TBasePathData.h (.../TBasePathData.h) (revision be30619d750d8663d54cf02e7d4bde2ed2dd8d05) +++ src/libchcore/TBasePathData.h (.../TBasePathData.h) (revision d88274a4bbfd4ef005d44c4d179b7596cb627486) @@ -35,10 +35,15 @@ public: TBasePathData(); TBasePathData(const TBasePathData& rEntry); +/* - void SetMove(bool bValue) { m_bMove=bValue; } + void SetMove(bool bValue) { m_bMove = bValue; } bool GetMove() const { return m_bMove; } +*/ + bool GetSkipFurtherProcessing() const { return m_bSkipFurtherProcessing; } + void SetSkipFurtherProcessing(bool bSkipFurtherProcessing) { m_bSkipFurtherProcessing = bSkipFurtherProcessing; } + void SetDestinationPath(const TSmartPath& strPath); TSmartPath GetDestinationPath() const; bool IsDestinationPathSet() const { return !m_pathDst.IsEmpty(); } @@ -47,8 +52,8 @@ void Serialize(TWriteBinarySerializer& rSerializer, bool bData); private: - bool m_bMove; // specifies if we can use MoveFile (if will be moved) - + //bool m_bMove; // specifies if we can use MoveFile (if will be moved) + bool m_bSkipFurtherProcessing; // specifies if the path should be (or not) processed further TSmartPath m_pathDst; // dest path }; Index: src/libchcore/TSubTaskArray.cpp =================================================================== diff -u -N -r835e0344e9677ff02eb3b539061c48c9f3a616ce -rd88274a4bbfd4ef005d44c4d179b7596cb627486 --- src/libchcore/TSubTaskArray.cpp (.../TSubTaskArray.cpp) (revision 835e0344e9677ff02eb3b539061c48c9f3a616ce) +++ src/libchcore/TSubTaskArray.cpp (.../TSubTaskArray.cpp) (revision d88274a4bbfd4ef005d44c4d179b7596cb627486) @@ -30,6 +30,7 @@ #include "TSubTaskContext.h" #include "TBasicProgressInfo.h" #include "TTaskLocalStats.h" +#include "TSubTaskFastMove.h" BEGIN_CHCORE_NAMESPACE @@ -49,10 +50,12 @@ } case eOperation_Move: { - TSubTaskBasePtr spOperation = boost::make_shared(boost::ref(rSubTaskContext)); + TSubTaskBasePtr spOperation = boost::make_shared(boost::ref(rSubTaskContext)); m_vSubTasks.push_back(boost::make_tuple(spOperation, 0.05, true)); + spOperation = boost::make_shared(boost::ref(rSubTaskContext)); + m_vSubTasks.push_back(boost::make_tuple(spOperation, 0.05, false)); spOperation = boost::make_shared(boost::ref(rSubTaskContext)); - m_vSubTasks.push_back(boost::make_tuple(spOperation, 0.90, false)); + m_vSubTasks.push_back(boost::make_tuple(spOperation, 0.85, false)); spOperation = boost::make_shared(boost::ref(rSubTaskContext)); m_vSubTasks.push_back(boost::make_tuple(spOperation, 0.05, false)); Index: src/libchcore/TSubTaskBase.cpp =================================================================== diff -u -N -r25b3c85ea493809ee084271d5101a015d349da95 -rd88274a4bbfd4ef005d44c4d179b7596cb627486 --- src/libchcore/TSubTaskBase.cpp (.../TSubTaskBase.cpp) (revision 25b3c85ea493809ee084271d5101a015d349da95) +++ src/libchcore/TSubTaskBase.cpp (.../TSubTaskBase.cpp) (revision d88274a4bbfd4ef005d44c4d179b7596cb627486) @@ -66,13 +66,19 @@ { size_t stSrcIndex = spFileInfo->GetSrcIndex(); - if (!(iFlags & 0x01) && stSrcIndex != std::numeric_limits::max()) + if(!(iFlags & 0x01) && stSrcIndex != std::numeric_limits::max()) { // generate new dest name if(!rSourcePathsInfo.GetAt(stSrcIndex)->IsDestinationPathSet()) { - TSmartPath pathSubst = FindFreeSubstituteName(spFileInfo->GetFullFilePath(), pathDst); - rSourcePathsInfo.GetAt(stSrcIndex)->SetDestinationPath(pathSubst); + // generate something - if dest folder == src folder - search for copy + if(pathDst == spFileInfo->GetFullFilePath().GetFileRoot()) + { + TSmartPath pathSubst = FindFreeSubstituteName(spFileInfo->GetFullFilePath(), pathDst); + rSourcePathsInfo.GetAt(stSrcIndex)->SetDestinationPath(pathSubst); + } + else + rSourcePathsInfo.GetAt(stSrcIndex)->SetDestinationPath(spFileInfo->GetFullFilePath().GetFileName()); } return pathDst + rSourcePathsInfo.GetAt(stSrcIndex)->GetDestinationPath() + spFileInfo->GetFilePath(); Index: src/libchcore/TSubTaskBase.h =================================================================== diff -u -N -r835e0344e9677ff02eb3b539061c48c9f3a616ce -rd88274a4bbfd4ef005d44c4d179b7596cb627486 --- src/libchcore/TSubTaskBase.h (.../TSubTaskBase.h) (revision 835e0344e9677ff02eb3b539061c48c9f3a616ce) +++ src/libchcore/TSubTaskBase.h (.../TSubTaskBase.h) (revision d88274a4bbfd4ef005d44c4d179b7596cb627486) @@ -60,7 +60,7 @@ protected: // some common operations - TSmartPath CalculateDestinationPath(const TFileInfoPtr& spFileInfo, TSmartPath strPath, int iFlags) const; + TSmartPath CalculateDestinationPath(const TFileInfoPtr& spFileInfo, TSmartPath pathDst, int iFlags) const; TSmartPath FindFreeSubstituteName(TSmartPath pathSrcPath, TSmartPath pathDstPath) const; private: Index: src/libchcore/TSubTaskCopyMove.cpp =================================================================== diff -u -N -r25b3c85ea493809ee084271d5101a015d349da95 -rd88274a4bbfd4ef005d44c4d179b7596cb627486 --- src/libchcore/TSubTaskCopyMove.cpp (.../TSubTaskCopyMove.cpp) (revision 25b3c85ea493809ee084271d5101a015d349da95) +++ src/libchcore/TSubTaskCopyMove.cpp (.../TSubTaskCopyMove.cpp) (revision d88274a4bbfd4ef005d44c4d179b7596cb627486) @@ -146,23 +146,21 @@ ccp.pathDstFile = CalculateDestinationPath(spFileInfo, rTaskDefinition.GetDestinationPath(), ((int)bForceDirectories) << 1 | (int)bIgnoreFolders); // are the files/folders lie on the same partition ? - wchar_t wchDestinationDrive = rTaskDefinition.GetDestinationPath().GetDriveLetter(); bool bMove = rTaskDefinition.GetOperationType() == eOperation_Move; TSmartPath pathCurrent = spFileInfo->GetFullFilePath(); - if(bMove && wchDestinationDrive != L'\0' && wchDestinationDrive == pathCurrent.GetDriveLetter() && GetMove(spFileInfo)) + // if folder - create it + if(spFileInfo->IsDirectory()) { bool bRetry = true; - if(bRetry && !TLocalFilesystem::FastMove(pathCurrent, ccp.pathDstFile)) + if(bRetry && !TLocalFilesystem::CreateDirectory(ccp.pathDstFile, false) && (dwLastError=GetLastError()) != ERROR_ALREADY_EXISTS ) { - dwLastError=GetLastError(); - //log - strFormat = _T("Error %errno while calling MoveFile %srcpath -> %dstpath (ProcessFiles)"); + // log + strFormat = _T("Error %errno while calling CreateDirectory %path (ProcessFiles)"); strFormat.Replace(_T("%errno"), boost::lexical_cast(dwLastError).c_str()); - strFormat.Replace(_T("%srcpath"), spFileInfo->GetFullFilePath().ToString()); - strFormat.Replace(_T("%dstpath"), ccp.pathDstFile.ToString()); + strFormat.Replace(_T("%path"), ccp.pathDstFile.ToString()); rLog.loge(strFormat); - FEEDBACK_FILEERROR ferr = { spFileInfo->GetFullFilePath().ToString(), ccp.pathDstFile.ToString(), eFastMoveError, dwLastError }; + FEEDBACK_FILEERROR ferr = { ccp.pathDstFile.ToString(), NULL, eCreateError, dwLastError }; IFeedbackHandler::EFeedbackResult frResult = (IFeedbackHandler::EFeedbackResult)piFeedbackHandler->RequestFeedback(IFeedbackHandler::eFT_FileError, &ferr); switch(frResult) { @@ -183,79 +181,40 @@ THROW_CORE_EXCEPTION(eErr_UnhandledCase); } } - else - spFileInfo->SetFlags(FIF_PROCESSED, FIF_PROCESSED); + + rLocalStats.IncreaseProcessedSize(spFileInfo->GetLength64()); + spFileInfo->SetFlags(FIF_PROCESSED, FIF_PROCESSED); } else { - // if folder - create it - if(spFileInfo->IsDirectory()) - { - bool bRetry = true; - if(bRetry && !TLocalFilesystem::CreateDirectory(ccp.pathDstFile, false) && (dwLastError=GetLastError()) != ERROR_ALREADY_EXISTS ) - { - // log - strFormat = _T("Error %errno while calling CreateDirectory %path (ProcessFiles)"); - strFormat.Replace(_T("%errno"), boost::lexical_cast(dwLastError).c_str()); - strFormat.Replace(_T("%path"), ccp.pathDstFile.ToString()); - rLog.loge(strFormat); + // start copying/moving file + ccp.spSrcFile = spFileInfo; + ccp.bProcessed = false; - FEEDBACK_FILEERROR ferr = { ccp.pathDstFile.ToString(), NULL, eCreateError, dwLastError }; - IFeedbackHandler::EFeedbackResult frResult = (IFeedbackHandler::EFeedbackResult)piFeedbackHandler->RequestFeedback(IFeedbackHandler::eFT_FileError, &ferr); - switch(frResult) - { - case IFeedbackHandler::eResult_Cancel: - return TSubTaskBase::eSubResult_CancelRequest; + // copy data + TSubTaskBase::ESubOperationResult eResult = CustomCopyFileFB(&ccp); + if(eResult != TSubTaskBase::eSubResult_Continue) + return eResult; - case IFeedbackHandler::eResult_Retry: - continue; + spFileInfo->SetFlags(ccp.bProcessed ? FIF_PROCESSED : 0, FIF_PROCESSED); - case IFeedbackHandler::eResult_Pause: - return TSubTaskBase::eSubResult_PauseRequest; - - case IFeedbackHandler::eResult_Skip: - bRetry = false; - break; // just do nothing - default: - BOOST_ASSERT(FALSE); // unknown result - THROW_CORE_EXCEPTION(eErr_UnhandledCase); - } - } - - rLocalStats.IncreaseProcessedSize(spFileInfo->GetLength64()); - spFileInfo->SetFlags(FIF_PROCESSED, FIF_PROCESSED); - } - else + // if moving - delete file (only if config flag is set) + if(bMove && spFileInfo->GetFlags() & FIF_PROCESSED && !GetTaskPropValue(rTaskDefinition.GetConfiguration())) { - // start copying/moving file - ccp.spSrcFile = spFileInfo; - ccp.bProcessed = false; - - // copy data - TSubTaskBase::ESubOperationResult eResult = CustomCopyFileFB(&ccp); - if(eResult != TSubTaskBase::eSubResult_Continue) - return eResult; - - spFileInfo->SetFlags(ccp.bProcessed ? FIF_PROCESSED : 0, FIF_PROCESSED); - - // if moving - delete file (only if config flag is set) - if(bMove && spFileInfo->GetFlags() & FIF_PROCESSED && !GetTaskPropValue(rTaskDefinition.GetConfiguration())) - { - if(!GetTaskPropValue(rTaskDefinition.GetConfiguration())) - TLocalFilesystem::SetAttributes(spFileInfo->GetFullFilePath(), FILE_ATTRIBUTE_NORMAL); - TLocalFilesystem::DeleteFile(spFileInfo->GetFullFilePath()); // there will be another try later, so I don't check - // if succeeded - } + if(!GetTaskPropValue(rTaskDefinition.GetConfiguration())) + TLocalFilesystem::SetAttributes(spFileInfo->GetFullFilePath(), FILE_ATTRIBUTE_NORMAL); + TLocalFilesystem::DeleteFile(spFileInfo->GetFullFilePath()); // there will be another try later, so we don't check + // if succeeded } + } - // set a time - if(GetTaskPropValue(rTaskDefinition.GetConfiguration())) - TLocalFilesystem::SetFileDirectoryTime(ccp.pathDstFile, spFileInfo->GetCreationTime(), spFileInfo->GetLastAccessTime(), spFileInfo->GetLastWriteTime()); // no error checking (but most probably it should be checked) + // set a time + if(GetTaskPropValue(rTaskDefinition.GetConfiguration())) + TLocalFilesystem::SetFileDirectoryTime(ccp.pathDstFile, spFileInfo->GetCreationTime(), spFileInfo->GetLastAccessTime(), spFileInfo->GetLastWriteTime()); // no error checking (but most probably it should be checked) - // attributes - if(GetTaskPropValue(rTaskDefinition.GetConfiguration())) - TLocalFilesystem::SetAttributes(ccp.pathDstFile, spFileInfo->GetAttributes()); // as above - } + // attributes + if(GetTaskPropValue(rTaskDefinition.GetConfiguration())) + TLocalFilesystem::SetAttributes(ccp.pathDstFile, spFileInfo->GetAttributes()); // as above rBasicProgressInfo.SetCurrentIndex(stIndex + 1); } @@ -272,22 +231,6 @@ return TSubTaskBase::eSubResult_Continue; } -bool TSubTaskCopyMove::GetMove(const TFileInfoPtr& spFileInfo) -{ - if(!spFileInfo) - THROW_CORE_EXCEPTION(eErr_InvalidArgument); - if(spFileInfo->GetSrcIndex() == std::numeric_limits::max()) - THROW_CORE_EXCEPTION(eErr_InvalidArgument); - - // check if this information has already been stored - size_t stBaseIndex = spFileInfo->GetSrcIndex(); - if(stBaseIndex >= GetContext().GetBasePathDataContainer().GetCount()) - THROW_CORE_EXCEPTION(eErr_BoundsExceeded); - - TBasePathDataPtr spPathData = GetContext().GetBasePathDataContainer().GetAt(stBaseIndex); - return spPathData->GetMove(); -} - int TSubTaskCopyMove::GetBufferIndex(const TFileInfoPtr& spFileInfo) { if(!spFileInfo) Index: src/libchcore/TSubTaskCopyMove.h =================================================================== diff -u -N -r835e0344e9677ff02eb3b539061c48c9f3a616ce -rd88274a4bbfd4ef005d44c4d179b7596cb627486 --- src/libchcore/TSubTaskCopyMove.h (.../TSubTaskCopyMove.h) (revision 835e0344e9677ff02eb3b539061c48c9f3a616ce) +++ src/libchcore/TSubTaskCopyMove.h (.../TSubTaskCopyMove.h) (revision d88274a4bbfd4ef005d44c4d179b7596cb627486) @@ -42,7 +42,6 @@ virtual ESubOperationType GetSubOperationType() const { return eSubOperation_Copying; } private: - bool GetMove(const TFileInfoPtr& spFileInfo); int GetBufferIndex(const TFileInfoPtr& spFileInfo); ESubOperationResult CustomCopyFileFB(CUSTOM_COPY_PARAMS* pData); Index: src/libchcore/TSubTaskFastMove.cpp =================================================================== diff -u -N --- src/libchcore/TSubTaskFastMove.cpp (revision 0) +++ src/libchcore/TSubTaskFastMove.cpp (revision d88274a4bbfd4ef005d44c4d179b7596cb627486) @@ -0,0 +1,208 @@ +// ============================================================================ +// Copyright (C) 2001-2009 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. +// ============================================================================ +/// @file TSubTaskScanDirectory.cpp +/// @date 2010/09/18 +/// @brief Contains implementation of classes related to scan directory subtask. +// ============================================================================ +#include "stdafx.h" +#include "TSubTaskFastMove.h" +#include +#include "TSubTaskContext.h" +#include "TTaskConfiguration.h" +#include "TTaskDefinition.h" +#include "TLocalFilesystem.h" +#include "FeedbackHandlerBase.h" +#include "TBasePathData.h" +#include "TWorkerThreadController.h" +#include "TTaskLocalStats.h" +#include "..\libicpf\log.h" +#include "TFileInfo.h" +#include "TBasicProgressInfo.h" +#include + +BEGIN_CHCORE_NAMESPACE + +TSubTaskFastMove::TSubTaskFastMove(TSubTaskContext& rContext) : + TSubTaskBase(rContext) +{ +} + +TSubTaskFastMove::~TSubTaskFastMove() +{ +} + +TSubTaskFastMove::ESubOperationResult TSubTaskFastMove::Exec() +{ + // log + icpf::log_file& rLog = GetContext().GetLog(); + TTaskDefinition& rTaskDefinition = GetContext().GetTaskDefinition(); + IFeedbackHandler* piFeedbackHandler = GetContext().GetFeedbackHandler(); + TWorkerThreadController& rThreadController = GetContext().GetThreadController(); + TTaskLocalStats& rTaskLocalStats = GetContext().GetTaskLocalStats(); + TTaskBasicProgressInfo& rProgressInfo = GetContext().GetTaskBasicProgressInfo(); + TBasePathDataContainer& rBasePathDataContainer = GetContext().GetBasePathDataContainer(); + + rLog.logi(_T("Performing initial fast-move operation...")); + + // reset progress + rTaskLocalStats.SetProcessedSize(0); + rTaskLocalStats.SetTotalSize(0); + + // read filtering options + TFileFiltersArray afFilters; + GetTaskPropValue(rTaskDefinition.GetConfiguration(), afFilters); + + //wchar_t wchDestinationDriveLetter = rTaskDefinition.GetDestinationPath().GetDriveLetter(); + + bool bIgnoreDirs = GetTaskPropValue(rTaskDefinition.GetConfiguration()); + bool bForceDirectories = GetTaskPropValue(rTaskDefinition.GetConfiguration()); + + // when using special options with move operation, we don't want to use fast-moving, since most probably + // some searching and special processing needs to be done + if(bIgnoreDirs || bForceDirectories) + return eSubResult_Continue; + + // add everything + TString strFormat; + bool bRetry = true; + bool bSkipInputPath = false; + + size_t stSize = rTaskDefinition.GetSourcePathCount(); + for(size_t stIndex = rProgressInfo.GetCurrentIndex(); stIndex < stSize ; stIndex++) + { + // store currently processed index + rProgressInfo.SetCurrentIndex(stIndex); + + // retrieve base path data + TBasePathDataPtr spBasePathData = rBasePathDataContainer.GetAt(stIndex); + if(!spBasePathData) + THROW_CORE_EXCEPTION(eErr_InvalidPointer); + + // check if we want to process this path at all + if(spBasePathData->GetSkipFurtherProcessing()) + continue; + + TFileInfoPtr spFileInfo(boost::make_shared()); + bSkipInputPath = false; + // try to get some info about the input path; let user know if the path does not exist. + do + { + bRetry = false; + + // read attributes of src file/folder + bool bExists = TLocalFilesystem::GetFileInfo(rTaskDefinition.GetSourcePathAt(stIndex), spFileInfo, stIndex, &rTaskDefinition.GetSourcePaths()); + if(!bExists) + { + FEEDBACK_FILEERROR ferr = { rTaskDefinition.GetSourcePathAt(stIndex).ToString(), NULL, eFastMoveError, ERROR_FILE_NOT_FOUND }; + IFeedbackHandler::EFeedbackResult frResult = (IFeedbackHandler::EFeedbackResult)piFeedbackHandler->RequestFeedback(IFeedbackHandler::eFT_FileError, &ferr); + switch(frResult) + { + case IFeedbackHandler::eResult_Cancel: + return eSubResult_CancelRequest; + + case IFeedbackHandler::eResult_Retry: + bRetry = true; + break; + + case IFeedbackHandler::eResult_Pause: + return eSubResult_PauseRequest; + + case IFeedbackHandler::eResult_Skip: + bSkipInputPath = true; + break; // just do nothing + + default: + BOOST_ASSERT(FALSE); // unknown result + THROW_CORE_EXCEPTION(eErr_UnhandledCase); + } + } + } + while(bRetry); + + // if we have chosen to skip the input path then there's nothing to do + if(bSkipInputPath) + continue; + + // does it match the input filter? + if(!spFileInfo->IsDirectory() && !afFilters.Match(spFileInfo)) + { + spBasePathData->SetSkipFurtherProcessing(true); + continue; + } + + // try to fast move + bRetry = true; + bool bResult = true; + do + { + bResult = TLocalFilesystem::FastMove(rTaskDefinition.GetSourcePathAt(stIndex), CalculateDestinationPath(spFileInfo, rTaskDefinition.GetDestinationPath(), 0)); + if(!bResult) + { + DWORD dwLastError = GetLastError(); + + //log + 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"), rTaskDefinition.GetDestinationPath().ToString()); + rLog.loge(strFormat); + + FEEDBACK_FILEERROR ferr = { rTaskDefinition.GetSourcePathAt(stIndex).ToString(), rTaskDefinition.GetDestinationPath().ToString(), eFastMoveError, dwLastError }; + IFeedbackHandler::EFeedbackResult frResult = (IFeedbackHandler::EFeedbackResult)piFeedbackHandler->RequestFeedback(IFeedbackHandler::eFT_FileError, &ferr); + switch(frResult) + { + case IFeedbackHandler::eResult_Cancel: + return TSubTaskBase::eSubResult_CancelRequest; + + case IFeedbackHandler::eResult_Retry: + continue; + + case IFeedbackHandler::eResult_Pause: + return TSubTaskBase::eSubResult_PauseRequest; + + case IFeedbackHandler::eResult_Skip: + //bSkipInputPath = true; // not needed, since we will break the loop anyway and there is no other processing for this path either + bRetry = false; + break; // just do nothing + default: + BOOST_ASSERT(FALSE); // unknown result + THROW_CORE_EXCEPTION(eErr_UnhandledCase); + } + } + else + spBasePathData->SetSkipFurtherProcessing(true); // mark that this path should not be processed any further + } + while(!bResult && bRetry); + + // check for kill need + if(rThreadController.KillRequested()) + { + // log + rLog.logi(_T("Kill request while adding data to files array (RecurseDirectories)")); + return eSubResult_KillRequest; + } + } + + // log + rLog.logi(_T("Fast moving finished")); + + return eSubResult_Continue; +} + +END_CHCORE_NAMESPACE Index: src/libchcore/TSubTaskFastMove.h =================================================================== diff -u -N --- src/libchcore/TSubTaskFastMove.h (revision 0) +++ src/libchcore/TSubTaskFastMove.h (revision d88274a4bbfd4ef005d44c4d179b7596cb627486) @@ -0,0 +1,52 @@ +// ============================================================================ +// Copyright (C) 2001-2009 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. +// ============================================================================ +/// @file TSubTaskFastMove.h +/// @date 2011/11/13 +/// @brief Contains declarations of classes responsible for fast move subtask. +// ============================================================================ +#ifndef __TSUBTASKFASTMOVE_H__ +#define __TSUBTASKFASTMOVE_H__ + +#include "libchcore.h" +#include "TSubTaskBase.h" +#include "TPath.h" + +BEGIN_CHCORE_NAMESPACE + +class TFileFiltersArray; + +/////////////////////////////////////////////////////////////////////////// +// TSubTaskFastMove + +class LIBCHCORE_API TSubTaskFastMove : public TSubTaskBase +{ +public: + TSubTaskFastMove(TSubTaskContext& rContext); + virtual ~TSubTaskFastMove(); + + virtual ESubOperationResult Exec(); + virtual ESubOperationType GetSubOperationType() const { return eSubOperation_Scanning; } + +private: + int ScanDirectory(TSmartPath pathDirName, size_t stSrcIndex, bool bRecurse, bool bIncludeDirs, TFileFiltersArray& afFilters); +}; + +END_CHCORE_NAMESPACE + +#endif Index: src/libchcore/TSubTaskScanDirectory.cpp =================================================================== diff -u -N -r7365307e6b78c9bc9db376635405e8c69d786381 -rd88274a4bbfd4ef005d44c4d179b7596cb627486 --- src/libchcore/TSubTaskScanDirectory.cpp (.../TSubTaskScanDirectory.cpp) (revision 7365307e6b78c9bc9db376635405e8c69d786381) +++ src/libchcore/TSubTaskScanDirectory.cpp (.../TSubTaskScanDirectory.cpp) (revision d88274a4bbfd4ef005d44c4d179b7596cb627486) @@ -54,9 +54,9 @@ TFileInfoArray& rFilesCache = GetContext().GetFilesCache(); TTaskDefinition& rTaskDefinition = GetContext().GetTaskDefinition(); IFeedbackHandler* piFeedbackHandler = GetContext().GetFeedbackHandler(); - const TBasePathDataContainer& rarrSourcePathsInfo = GetContext().GetBasePathDataContainer(); TWorkerThreadController& rThreadController = GetContext().GetThreadController(); TTaskLocalStats& rTaskLocalStats = GetContext().GetTaskLocalStats(); + TBasePathDataContainer& rBasePathDataContainer = GetContext().GetBasePathDataContainer(); rLog.logi(_T("Searching for files...")); @@ -72,12 +72,8 @@ TFileFiltersArray afFilters; GetTaskPropValue(rTaskDefinition.GetConfiguration(), afFilters); - // enter some data to rFilesCache - wchar_t wchDestinationDriveLetter = rTaskDefinition.GetDestinationPath().GetDriveLetter(); - bool bIgnoreDirs = GetTaskPropValue(rTaskDefinition.GetConfiguration()); bool bForceDirectories = GetTaskPropValue(rTaskDefinition.GetConfiguration()); - bool bMove = rTaskDefinition.GetOperationType() == eOperation_Move; // add everything TString strFormat; @@ -87,12 +83,18 @@ size_t stSize = rTaskDefinition.GetSourcePathCount(); for(size_t stIndex = 0; stIndex < stSize ; stIndex++) { - TFileInfoPtr spFileInfo; - bSkipInputPath = false; + TFileInfoPtr spFileInfo(boost::make_shared()); - spFileInfo.reset(new TFileInfo()); + // retrieve base path data + TBasePathDataPtr spBasePathData = rBasePathDataContainer.GetAt(stIndex); + if(!spBasePathData) + THROW_CORE_EXCEPTION(eErr_InvalidPointer); + // check if we want to process this path at all (might be already fast moved) + if(spBasePathData->GetSkipFurtherProcessing()) + continue; + // try to get some info about the input path; let user know if the path does not exist. do { @@ -139,8 +141,6 @@ strFormat.Replace(_T("%path"), rTaskDefinition.GetSourcePathAt(stIndex).ToString()); rLog.logi(strFormat); - wchar_t wchSourceDriveLetter = spFileInfo->GetFullFilePath().GetDriveLetter(); - // add if needed if(spFileInfo->IsDirectory()) { @@ -157,20 +157,13 @@ } // don't add folder contents when moving inside one disk boundary - if(bIgnoreDirs || !bMove || wchDestinationDriveLetter == L'\0' || wchDestinationDriveLetter != wchSourceDriveLetter || - TLocalFilesystem::PathExist(CalculateDestinationPath(spFileInfo, rTaskDefinition.GetDestinationPath(), ((int)bForceDirectories) << 1)) ) - { - // log - strFormat = _T("Recursing folder %path"); - strFormat.Replace(_t("%path"), spFileInfo->GetFullFilePath().ToString()); - rLog.logi(strFormat); + // log + strFormat = _T("Recursing folder %path"); + strFormat.Replace(_t("%path"), spFileInfo->GetFullFilePath().ToString()); + rLog.logi(strFormat); - // no movefile possibility - use CustomCopyFileFB - rarrSourcePathsInfo.GetAt(stIndex)->SetMove(false); + ScanDirectory(spFileInfo->GetFullFilePath(), stIndex, true, !bIgnoreDirs || bForceDirectories, afFilters); - ScanDirectory(spFileInfo->GetFullFilePath(), stIndex, true, !bIgnoreDirs || bForceDirectories, afFilters); - } - // check for kill need if(rThreadController.KillRequested()) { @@ -182,16 +175,6 @@ } else { - if(bMove && wchDestinationDriveLetter != L'\0' && wchDestinationDriveLetter == wchSourceDriveLetter && - !TLocalFilesystem::PathExist(CalculateDestinationPath(spFileInfo, rTaskDefinition.GetDestinationPath(), ((int)bForceDirectories) << 1)) ) - { - // if moving within one partition boundary set the file size to 0 so the overall size will - // be ok - spFileInfo->SetLength64(0); - } - else - rarrSourcePathsInfo.GetAt(stIndex)->SetMove(false); // no MoveFile - // add file info if passes filters if(afFilters.Match(spFileInfo)) rFilesCache.AddFileInfo(spFileInfo); Index: src/libchcore/libchcore.vc90.vcproj =================================================================== diff -u -N -r835e0344e9677ff02eb3b539061c48c9f3a616ce -rd88274a4bbfd4ef005d44c4d179b7596cb627486 --- src/libchcore/libchcore.vc90.vcproj (.../libchcore.vc90.vcproj) (revision 835e0344e9677ff02eb3b539061c48c9f3a616ce) +++ src/libchcore/libchcore.vc90.vcproj (.../libchcore.vc90.vcproj) (revision d88274a4bbfd4ef005d44c4d179b7596cb627486) @@ -1,7 +1,7 @@ + + + +