Index: src/libchcore/TSubTaskCopyMove.cpp =================================================================== diff -u -N -rb941384e121190b6107f1c99b3233667e3daf4ce -r734408890246965d47e6bbf2c2978371269dd1fd --- src/libchcore/TSubTaskCopyMove.cpp (.../TSubTaskCopyMove.cpp) (revision b941384e121190b6107f1c99b3233667e3daf4ce) +++ src/libchcore/TSubTaskCopyMove.cpp (.../TSubTaskCopyMove.cpp) (revision 734408890246965d47e6bbf2c2978371269dd1fd) @@ -40,13 +40,12 @@ #include "TOverlappedMemoryPool.h" #include "TOverlappedDataBuffer.h" #include "RoundingFunctions.h" -#include #include "TTaskConfigBufferSizes.h" #include "TFileException.h" #include "TFilesystemFeedbackWrapper.h" #include "TFilesystemFileFeedbackWrapper.h" #include "TDestinationPathProvider.h" -#include "TOverlappedReaderWriter.h" +#include "TOverlappedReaderWriterFB.h" namespace chcore { @@ -71,14 +70,14 @@ TSubTaskCopyMove::TSubTaskCopyMove(TSubTaskContext& rContext) : TSubTaskBase(rContext), - m_tSubTaskStats(eSubOperation_Copying), + m_spSubTaskStats(std::make_shared(eSubOperation_Copying)), m_spLog(std::make_unique(rContext.GetLogFileData(), L"ST-CopyMove")) { } void TSubTaskCopyMove::Reset() { - m_tSubTaskStats.Clear(); + m_spSubTaskStats->Clear(); } void TSubTaskCopyMove::InitBeforeExec() @@ -88,21 +87,21 @@ file_count_t fcCount = rFilesCache.GetSize(); if(fcCount == 0) { - m_tSubTaskStats.SetCurrentPath(TString()); + m_spSubTaskStats->SetCurrentPath(TString()); return; } - file_count_t fcIndex = m_tSubTaskStats.GetCurrentIndex(); + file_count_t fcIndex = m_spSubTaskStats->GetCurrentIndex(); if(fcIndex >= fcCount) fcIndex = 0; TFileInfoPtr spFileInfo = rFilesCache.GetAt(fcIndex); - m_tSubTaskStats.SetCurrentPath(spFileInfo->GetFullFilePath().ToString()); + m_spSubTaskStats->SetCurrentPath(spFileInfo->GetFullFilePath().ToString()); } TSubTaskBase::ESubOperationResult TSubTaskCopyMove::Exec(const IFeedbackHandlerPtr& spFeedback) { - TScopedRunningTimeTracker guard(m_tSubTaskStats); + TScopedRunningTimeTracker guard(*m_spSubTaskStats); TFeedbackHandlerWrapperPtr spFeedbackHandler(std::make_shared(spFeedback, guard)); TFileInfoArray& rFilesCache = GetContext().GetFilesCache(); @@ -120,27 +119,27 @@ // initialize stats if not resuming (when resuming we have already initialized // the stats once - it is being restored in Load() too). - if (!m_tSubTaskStats.IsInitialized()) - m_tSubTaskStats.Init(TBufferSizes::eBuffer_Default, rFilesCache.GetSize(), 0, rFilesCache.CalculateTotalSize(), rFilesCache.CalculatePartialSize(m_tSubTaskStats.GetCurrentIndex()), TString()); + if (!m_spSubTaskStats->IsInitialized()) + m_spSubTaskStats->Init(TBufferSizes::eBuffer_Default, rFilesCache.GetSize(), 0, rFilesCache.CalculateTotalSize(), rFilesCache.CalculatePartialSize(m_spSubTaskStats->GetCurrentIndex()), TString()); else { - _ASSERTE(rFilesCache.GetSize() == m_tSubTaskStats.GetTotalCount()); - if (rFilesCache.GetSize() != m_tSubTaskStats.GetTotalCount()) + _ASSERTE(rFilesCache.GetSize() == m_spSubTaskStats->GetTotalCount()); + if (rFilesCache.GetSize() != m_spSubTaskStats->GetTotalCount()) throw TCoreException(eErr_InternalProblem, L"Size of files' cache differs from stats information", LOCATION); } // now it's time to check if there is enough space on destination device - unsigned long long ullNeededSize = rFilesCache.CalculateTotalSize() - rFilesCache.CalculatePartialSize(m_tSubTaskStats.GetCurrentIndex()); + unsigned long long ullNeededSize = rFilesCache.CalculateTotalSize() - rFilesCache.CalculatePartialSize(m_spSubTaskStats->GetCurrentIndex()); TSmartPath pathSingleSrc = spSrcPaths->GetAt(0)->GetSrcPath(); TSubTaskBase::ESubOperationResult eResult = tFilesystemFBWrapper.CheckForFreeSpaceFB(pathSingleSrc, pathDestination, ullNeededSize); if(eResult != TSubTaskBase::eSubResult_Continue) return eResult; // begin at index which wasn't processed previously file_count_t fcSize = rFilesCache.GetSize(); - file_count_t fcIndex = m_tSubTaskStats.GetCurrentIndex(); - unsigned long long ullCurrentItemProcessedSize = m_tSubTaskStats.GetCurrentItemProcessedSize(); - bool bCurrentFileSilentResume = m_tSubTaskStats.CanCurrentItemSilentResume(); + file_count_t fcIndex = m_spSubTaskStats->GetCurrentIndex(); + unsigned long long ullCurrentItemProcessedSize = m_spSubTaskStats->GetCurrentItemProcessedSize(); + bool bCurrentFileSilentResume = m_spSubTaskStats->CanCurrentItemSilentResume(); // create a buffer of size m_nBufferSize CUSTOM_COPY_PARAMS ccp; @@ -186,12 +185,12 @@ TSmartPath pathCurrent = spFileInfo->GetFullFilePath(); // new stats - m_tSubTaskStats.SetCurrentIndex(fcIndex); - m_tSubTaskStats.SetProcessedCount(fcIndex); - m_tSubTaskStats.SetCurrentPath(pathCurrent.ToString()); - m_tSubTaskStats.SetCurrentItemSizes(ullCurrentItemProcessedSize, spFileInfo->GetLength64()); // preserve the processed size for the first item + m_spSubTaskStats->SetCurrentIndex(fcIndex); + m_spSubTaskStats->SetProcessedCount(fcIndex); + m_spSubTaskStats->SetCurrentPath(pathCurrent.ToString()); + m_spSubTaskStats->SetCurrentItemSizes(ullCurrentItemProcessedSize, spFileInfo->GetLength64()); // preserve the processed size for the first item ullCurrentItemProcessedSize = 0; // in next iteration we're not resuming anymore - m_tSubTaskStats.SetCurrentItemSilentResume(bCurrentFileSilentResume); + m_spSubTaskStats->SetCurrentItemSilentResume(bCurrentFileSilentResume); bCurrentFileSilentResume = false; // if the file was already processed (e.g. by fast-move), just consider the file skipped @@ -280,9 +279,9 @@ } // stats - m_tSubTaskStats.SetCurrentIndex(fcIndex); - m_tSubTaskStats.SetProcessedCount(fcIndex); - m_tSubTaskStats.SetCurrentPath(TString()); + m_spSubTaskStats->SetCurrentIndex(fcIndex); + m_spSubTaskStats->SetProcessedCount(fcIndex); + m_spSubTaskStats->SetCurrentPath(TString()); // log LOG_INFO(m_spLog) << _T("Finished processing in ProcessFiles"); @@ -292,7 +291,7 @@ void TSubTaskCopyMove::GetStatsSnapshot(TSubTaskStatsSnapshotPtr& spStats) const { - m_tSubTaskStats.GetSnapshot(spStats); + m_spSubTaskStats->GetSnapshot(spStats); // if this subtask is not started yet, try to get the most fresh information for processing if(!spStats->IsRunning() && spStats->GetTotalCount() == 0 && spStats->GetTotalSize() == 0) { @@ -350,11 +349,11 @@ IFilesystemFilePtr fileSrc = spFilesystem->CreateFileObject(pData->spSrcFile->GetFullFilePath(), bNoBuffer); IFilesystemFilePtr fileDst = spFilesystem->CreateFileObject(pData->pathDstFile, bNoBuffer); - TFilesystemFileFeedbackWrapper srcFileWrapper(fileSrc, spFeedbackHandler, GetContext().GetLogFileData(), rThreadController, spFilesystem); - TFilesystemFileFeedbackWrapper dstFileWrapper(fileDst, spFeedbackHandler, GetContext().GetLogFileData(), rThreadController, spFilesystem); + TFilesystemFileFeedbackWrapperPtr spSrcFileWrapper(std::make_shared(fileSrc, spFeedbackHandler, GetContext().GetLogFileData(), rThreadController, spFilesystem)); + TFilesystemFileFeedbackWrapperPtr spDstFileWrapper(std::make_shared(fileDst, spFeedbackHandler, GetContext().GetLogFileData(), rThreadController, spFilesystem)); bool bSkip = false; - TSubTaskBase::ESubOperationResult eResult = OpenSrcAndDstFilesFB(srcFileWrapper, dstFileWrapper, pData, bSkip); + TSubTaskBase::ESubOperationResult eResult = OpenSrcAndDstFilesFB(*spSrcFileWrapper, *spDstFileWrapper, pData, bSkip); if(eResult != TSubTaskBase::eSubResult_Continue) return eResult; else if(bSkip) @@ -367,256 +366,26 @@ // establish count of data to read TBufferSizes::EBufferType eBufferIndex = GetBufferIndex(pData->tBufferSizes, pData->spSrcFile); - m_tSubTaskStats.SetCurrentBufferIndex(eBufferIndex); + m_spSubTaskStats->SetCurrentBufferIndex(eBufferIndex); // determine buffer size to use for the operation DWORD dwCurrentBufferSize = RoundUp(pData->tBufferSizes.GetSizeByType(eBufferIndex), IFilesystemFile::MaxSectorSize); // resume copying from the position after the last processed mark; the proper value should be set // by OpenSrcAndDstFilesFB() - that includes the no-buffering setting if required. - unsigned long long ullNextReadPos = m_tSubTaskStats.GetCurrentItemProcessedSize(); + unsigned long long ullNextReadPos = m_spSubTaskStats->GetCurrentItemProcessedSize(); - TOverlappedReaderWriter tReaderWriter(m_spLog->GetLogFileData(), pData->spMemoryPool, ullNextReadPos, dwCurrentBufferSize); + TOverlappedReaderWriterFB tReaderWriter(spSrcFileWrapper, pData->spSrcFile, spDstFileWrapper, m_spSubTaskStats, m_spLog->GetLogFileData(), + pData->spMemoryPool, ullNextReadPos, dwCurrentBufferSize); - // read data from file to buffer - // NOTE: order is critical here: - // - write finished is first, so that all the data that were already queued to be written, will be written and accounted for (in stats) - // - kill request is second, so that we can stop processing as soon as all the data is written to destination location; - // that also means that we don't want to queue reads or writes anymore - all the data that were read until now, will be lost - // - write possible - we're prioritizing write queuing here to empty buffers as soon as possible - // - read possible - lowest priority - if we don't have anything to write or finalize , then read another part of source data - enum - { - eKillThread, eWriteFinished, eWriteFailed, eWritePossible, eReadFailed, eReadPossible, eHandleCount - }; - std::array arrHandles = { - rThreadController.GetKillThreadHandle(), - tReaderWriter.GetWriter()->GetEventWriteFinishedHandle(), - tReaderWriter.GetWriter()->GetEventWriteFailedHandle(), - tReaderWriter.GetWriter()->GetEventWritePossibleHandle(), - tReaderWriter.GetReader()->GetEventReadFailedHandle(), - tReaderWriter.GetReader()->GetEventReadPossibleHandle() - }; + eResult = tReaderWriter.Start(rThreadController.GetKillThreadHandle(), pData->bProcessed); - bool bStopProcessing = false; - while(!bStopProcessing) - { - DWORD dwResult = WaitForMultipleObjectsEx(eHandleCount, arrHandles.data(), false, INFINITE, true); - switch(dwResult) - { - case STATUS_USER_APC: - break; - - case WAIT_OBJECT_0 + eKillThread: - { - // log - LOG_INFO(m_spLog) << L"Kill request while main copying file " << pData->spSrcFile->GetFullFilePath().ToString() << - L" -> " << pData->pathDstFile.ToString(); - - eResult = TSubTaskBase::eSubResult_KillRequest; - bStopProcessing = true; - break; - } - - case WAIT_OBJECT_0 + eReadPossible: - { - TOverlappedDataBuffer* pBuffer = tReaderWriter.GetReader()->GetEmptyBuffer(); - if (!pBuffer) - throw TCoreException(eErr_InternalProblem, L"Read was possible, but no buffer is available", LOCATION); - - eResult = srcFileWrapper.ReadFileFB(*pBuffer, bSkip); - if(eResult != TSubTaskBase::eSubResult_Continue) - { - tReaderWriter.GetReader()->AddEmptyBuffer(pBuffer, false); - bStopProcessing = true; - } - else if(bSkip) - { - tReaderWriter.GetReader()->AddEmptyBuffer(pBuffer, false); - - AdjustProcessedSizeForSkip(pData->spSrcFile); - - pData->bProcessed = false; - bStopProcessing = true; - } - break; - } - case WAIT_OBJECT_0 + eReadFailed: - { - TOverlappedDataBuffer* pBuffer = tReaderWriter.GetReader()->GetFailedReadBuffer(); - if (!pBuffer) - throw TCoreException(eErr_InternalProblem, L"Cannot retrieve failed read buffer", LOCATION); - - // read error encountered - handle it - eResult = HandleReadError(spFeedbackHandler, *pBuffer, pData->spSrcFile->GetFullFilePath(), bSkip); - if(eResult == TSubTaskBase::eSubResult_Retry) - tReaderWriter.GetReader()->AddEmptyBuffer(pBuffer, true); - else if(eResult != TSubTaskBase::eSubResult_Continue) - { - tReaderWriter.GetReader()->AddEmptyBuffer(pBuffer, false); - bStopProcessing = true; - } - else if(bSkip) - { - tReaderWriter.GetReader()->AddEmptyBuffer(pBuffer, false); - - AdjustProcessedSizeForSkip(pData->spSrcFile); - - pData->bProcessed = false; - bStopProcessing = true; - } - - break; - } - case WAIT_OBJECT_0 + eWritePossible: - { - TOverlappedDataBuffer* pBuffer = tReaderWriter.GetWriter()->GetWriteBuffer(); - if (!pBuffer) - throw TCoreException(eErr_InternalProblem, L"Write was possible, but no buffer is available", LOCATION); - - eResult = dstFileWrapper.WriteFileFB(*pBuffer, bSkip); - if(eResult != TSubTaskBase::eSubResult_Continue) - { - tReaderWriter.GetReader()->AddEmptyBuffer(pBuffer, false); - bStopProcessing = true; - } - else if(bSkip) - { - tReaderWriter.GetReader()->AddEmptyBuffer(pBuffer, false); - - AdjustProcessedSizeForSkip(pData->spSrcFile); - - pData->bProcessed = false; - bStopProcessing = true; - } - - break; - } - - case WAIT_OBJECT_0 + eWriteFailed: - { - TOverlappedDataBuffer* pBuffer = tReaderWriter.GetWriter()->GetFailedWriteBuffer(); - if (!pBuffer) - throw TCoreException(eErr_InternalProblem, L"Failed to retrieve write failed buffer", LOCATION); - - eResult = HandleWriteError(spFeedbackHandler, *pBuffer, pData->pathDstFile, bSkip); - if(eResult == TSubTaskBase::eSubResult_Retry) - tReaderWriter.GetWriter()->AddFailedWriteBuffer(pBuffer); - else if(eResult != TSubTaskBase::eSubResult_Continue) - { - tReaderWriter.GetReader()->AddEmptyBuffer(pBuffer, false); - bStopProcessing = true; - } - else if(bSkip) - { - tReaderWriter.GetReader()->AddEmptyBuffer(pBuffer, false); - - AdjustProcessedSizeForSkip(pData->spSrcFile); - - pData->bProcessed = false; - bStopProcessing = true; - } - - break; - } - - case WAIT_OBJECT_0 + eWriteFinished: - { - TOverlappedDataBuffer* pBuffer = tReaderWriter.GetWriter()->GetFinishedBuffer(); - if (!pBuffer) - throw TCoreException(eErr_InternalProblem, L"Write finished was possible, but no buffer is available", LOCATION); - - if(pBuffer->IsLastPart()) - { - eResult = dstFileWrapper.FinalizeFileFB(*pBuffer, bSkip); - if (eResult != TSubTaskBase::eSubResult_Continue) - { - tReaderWriter.GetReader()->AddEmptyBuffer(pBuffer, false); - bStopProcessing = true; - break; - } - else if (bSkip) - { - tReaderWriter.GetReader()->AddEmptyBuffer(pBuffer, false); - - AdjustProcessedSizeForSkip(pData->spSrcFile); - - pData->bProcessed = false; - bStopProcessing = true; - break; - } - } - - file_size_t fsWritten = pBuffer->GetRealDataSize(); - - // in case we read past the original eof, try to get new file size from filesystem - AdjustProcessedSize(fsWritten, pData->spSrcFile, fileSrc); - - // stop iterating through file - bStopProcessing = pBuffer->IsLastPart(); - if(bStopProcessing) - { - tReaderWriter.GetWriter()->MarkAsFinalized(pBuffer); - - // this is the end of copying of src file - in case it is smaller than expected fix the stats so that difference is accounted for - AdjustFinalSize(pData->spSrcFile, fileSrc); - - pData->bProcessed = true; - m_tSubTaskStats.ResetCurrentItemProcessedSize(); - } - - tReaderWriter.GetReader()->AddEmptyBuffer(pBuffer, false); - - break; - } - - default: - throw TCoreException(eErr_UnhandledCase, L"Unknown result from async waiting function", LOCATION); - } - } - - tReaderWriter.WaitForMissingBuffersAndResetState(rThreadController.GetKillThreadHandle()); - return eResult; } - void TSubTaskCopyMove::AdjustProcessedSize(file_size_t fsWritten, const TFileInfoPtr& spSrcFileInfo, const IFilesystemFilePtr& spSrcFile) - { - // in case we read past the original eof, try to get new file size from filesystem - if (m_tSubTaskStats.WillAdjustProcessedSizeExceedTotalSize(0, fsWritten)) - { - file_size_t fsNewSize = spSrcFile->GetFileSize(); - if (fsNewSize == spSrcFileInfo->GetLength64()) - throw TCoreException(eErr_InternalProblem, L"Read more data from file than it really contained. Possible destination file corruption.", LOCATION); - - m_tSubTaskStats.AdjustTotalSize(spSrcFileInfo->GetLength64(), fsNewSize); - spSrcFileInfo->SetLength64(m_tSubTaskStats.GetCurrentItemTotalSize()); - } - - m_tSubTaskStats.AdjustProcessedSize(0, fsWritten); - } - - void TSubTaskCopyMove::AdjustFinalSize(const TFileInfoPtr& spSrcFileInfo, const IFilesystemFilePtr& spSrcFile) - { - unsigned long long ullCITotalSize = m_tSubTaskStats.GetCurrentItemTotalSize(); - unsigned long long ullCIProcessedSize = m_tSubTaskStats.GetCurrentItemProcessedSize(); - if (ullCIProcessedSize < ullCITotalSize) - { - file_size_t fsNewSize = spSrcFile->GetFileSize(); - if (fsNewSize == spSrcFileInfo->GetLength64()) - throw TCoreException(eErr_InternalProblem, L"Read less data from file than it really contained. Possible destination file corruption.", LOCATION); - - if (fsNewSize != ullCIProcessedSize) - throw TCoreException(eErr_InternalProblem, L"Updated file size still does not match the count of data read. Possible destination file corruption.", LOCATION); - - m_tSubTaskStats.AdjustTotalSize(ullCITotalSize, fsNewSize); - spSrcFileInfo->SetLength64(fsNewSize); - } - } - void TSubTaskCopyMove::AdjustProcessedSizeForSkip(const TFileInfoPtr& spSrcFileInfo) { - m_tSubTaskStats.AdjustProcessedSize(m_tSubTaskStats.GetCurrentItemProcessedSize(), spSrcFileInfo->GetLength64()); + m_spSubTaskStats->AdjustProcessedSize(m_spSubTaskStats->GetCurrentItemProcessedSize(), spSrcFileInfo->GetLength64()); } TSubTaskCopyMove::ESubOperationResult TSubTaskCopyMove::OpenSrcAndDstFilesFB(TFilesystemFileFeedbackWrapper& rSrcFile, TFilesystemFileFeedbackWrapper& rDstFile, @@ -627,7 +396,7 @@ bSkip = false; - unsigned long long ullProcessedSize = m_tSubTaskStats.GetCurrentItemProcessedSize(); + unsigned long long ullProcessedSize = m_spSubTaskStats->GetCurrentItemProcessedSize(); // first open the source file and handle any failures TSubTaskCopyMove::ESubOperationResult eResult = rSrcFile.OpenSourceFileFB(); @@ -652,7 +421,7 @@ file_size_t fsOldSize = pData->spSrcFile->GetLength64(); if(fsNewSize != fsOldSize) { - m_tSubTaskStats.AdjustTotalSize(fsOldSize, fsNewSize); + m_spSubTaskStats->AdjustTotalSize(fsOldSize, fsNewSize); pData->spSrcFile->SetLength64(fsNewSize); } @@ -662,7 +431,7 @@ // try to resume if possible bool bResumeSucceeded = false; - if (m_tSubTaskStats.CanCurrentItemSilentResume()) + if (m_spSubTaskStats->CanCurrentItemSilentResume()) { bool bContinue = true; TFileInfoPtr spDstFileInfo(std::make_shared()); @@ -739,7 +508,7 @@ throw TCoreException(eErr_InternalProblem, L"File position to move to is placed after the end of file", LOCATION); // adjust the stats for the difference between what was already processed and what will now be considered processed - m_tSubTaskStats.AdjustProcessedSize(ullProcessedSize, fsMoveTo); + m_spSubTaskStats->AdjustProcessedSize(ullProcessedSize, fsMoveTo); // if the destination file already exists - truncate it to the current file position if(!bDstFileFreshlyCreated) @@ -757,7 +526,7 @@ // at this point user already decided that he want to write data into destination file; // so if we're to resume copying after this point, we don't have to ask user for overwriting existing file - m_tSubTaskStats.SetCurrentItemSilentResume(true); + m_spSubTaskStats->SetCurrentItemSilentResume(true); return eResult; } @@ -792,90 +561,14 @@ return false; // buffer did not need adjusting } - TSubTaskBase::ESubOperationResult TSubTaskCopyMove::HandleReadError(const IFeedbackHandlerPtr& spFeedbackHandler, - TOverlappedDataBuffer& rBuffer, - const TSmartPath& pathFile, - bool& bSkip) - { - DWORD dwLastError = rBuffer.GetErrorCode(); - - bSkip = false; - - // log - 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()); - LOG_ERROR(m_spLog) << strFormat.c_str(); - - TFeedbackResult frResult = spFeedbackHandler->FileError(pathFile.ToWString(), TString(), EFileError::eReadError, dwLastError); - switch(frResult.GetResult()) - { - case EFeedbackResult::eResult_Cancel: - return TSubTaskBase::eSubResult_CancelRequest; - - case EFeedbackResult::eResult_Retry: - return TSubTaskBase::eSubResult_Retry; - - 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 TCoreException(eErr_UnhandledCase, L"Unknown feedback result", LOCATION); - } - } - - TSubTaskBase::ESubOperationResult TSubTaskCopyMove::HandleWriteError(const IFeedbackHandlerPtr& spFeedbackHandler, - TOverlappedDataBuffer& rBuffer, - const TSmartPath& pathFile, - bool& bSkip) - { - DWORD dwLastError = rBuffer.GetErrorCode(); - - bSkip = false; - - // log - TString strFormat = _T("Error %errno while trying to write %count bytes to destination file %path (CustomCopyFileFB)"); - strFormat.Replace(_T("%errno"), boost::lexical_cast(rBuffer.GetErrorCode()).c_str()); - strFormat.Replace(_T("%count"), boost::lexical_cast(rBuffer.GetBytesTransferred()).c_str()); - strFormat.Replace(_T("%path"), pathFile.ToString()); - LOG_ERROR(m_spLog) << strFormat.c_str(); - - TFeedbackResult frResult = spFeedbackHandler->FileError(pathFile.ToWString(), TString(), EFileError::eWriteError, dwLastError); - switch (frResult.GetResult()) - { - case EFeedbackResult::eResult_Cancel: - return TSubTaskBase::eSubResult_CancelRequest; - - case EFeedbackResult::eResult_Retry: - return TSubTaskBase::eSubResult_Retry; - - 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 TCoreException(eErr_UnhandledCase, L"Unknown feedback result", LOCATION); - } - } - void TSubTaskCopyMove::Store(const ISerializerPtr& spSerializer) const { ISerializerContainerPtr spContainer = spSerializer->GetContainer(_T("subtask_copymove")); InitColumns(spContainer); - ISerializerRowData& rRow = spContainer->GetRow(0, m_tSubTaskStats.WasAdded()); + ISerializerRowData& rRow = spContainer->GetRow(0, m_spSubTaskStats->WasAdded()); - m_tSubTaskStats.Store(rRow); + m_spSubTaskStats->Store(rRow); } void TSubTaskCopyMove::Load(const ISerializerPtr& spSerializer) @@ -886,7 +579,7 @@ ISerializerRowReaderPtr spRowReader = spContainer->GetRowReader(); if(spRowReader->Next()) - m_tSubTaskStats.Load(spRowReader); + m_spSubTaskStats->Load(spRowReader); } void TSubTaskCopyMove::InitColumns(const ISerializerContainerPtr& spContainer) const