Index: src/libchcore/TFilesystemFileFeedbackWrapper.cpp =================================================================== diff -u -r789d0908abf8db57e27cfeac7045d9962f4b522a -ra0de3c317cb73a42ed4efbdf29b3a87243b03df4 --- src/libchcore/TFilesystemFileFeedbackWrapper.cpp (.../TFilesystemFileFeedbackWrapper.cpp) (revision 789d0908abf8db57e27cfeac7045d9962f4b522a) +++ src/libchcore/TFilesystemFileFeedbackWrapper.cpp (.../TFilesystemFileFeedbackWrapper.cpp) (revision a0de3c317cb73a42ed4efbdf29b3a87243b03df4) @@ -379,6 +379,77 @@ } } + bool TFilesystemFileFeedbackWrapper::IsFreshlyCreated() const + { + return m_spFile->IsFreshlyCreated(); + } + + TSmartPath TFilesystemFileFeedbackWrapper::GetFilePath() const + { + return m_spFile->GetFilePath(); + } + + TSubTaskBase::ESubOperationResult TFilesystemFileFeedbackWrapper::GetFileSize(file_size_t& fsSize, bool& bSkip) const + { + bSkip = false; + + bool bRetry = false; + do + { + bRetry = false; + + DWORD dwLastError = ERROR_SUCCESS; + + try + { + fsSize = m_spFile->GetFileSize(); + 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"), m_spFile->GetFilePath().ToString()); + LOG_ERROR(m_spLog) << strFormat.c_str(); + + TFeedbackResult frResult = m_spFeedbackHandler->FileError(m_spFile->GetFilePath().ToWString(), TString(), EFileError::eFinalizeError, dwLastError); + switch(frResult.GetResult()) + { + 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 TCoreException(eErr_UnhandledCase, L"Feedback result unknown", LOCATION); + } + + if(WasKillRequested(frResult)) + return TSubTaskBase::eSubResult_KillRequest; + } + while(bRetry); + + return TSubTaskBase::eSubResult_Continue; + } + + file_size_t TFilesystemFileFeedbackWrapper::GetSeekPositionForResume(file_size_t fsLastAvailablePosition) + { + return m_spFile->GetSeekPositionForResume(fsLastAvailablePosition); + } + bool TFilesystemFileFeedbackWrapper::WasKillRequested(const TFeedbackResult& rFeedbackResult) const { if(m_rThreadController.KillRequested(rFeedbackResult.IsAutomatedReply() ? m_spFeedbackHandler->GetRetryInterval() : 0)) Index: src/libchcore/TFilesystemFileFeedbackWrapper.h =================================================================== diff -u -re7ca9e2c6306cd94e5e5caecc9cfdb3b562d3cdf -ra0de3c317cb73a42ed4efbdf29b3a87243b03df4 --- src/libchcore/TFilesystemFileFeedbackWrapper.h (.../TFilesystemFileFeedbackWrapper.h) (revision e7ca9e2c6306cd94e5e5caecc9cfdb3b562d3cdf) +++ src/libchcore/TFilesystemFileFeedbackWrapper.h (.../TFilesystemFileFeedbackWrapper.h) (revision a0de3c317cb73a42ed4efbdf29b3a87243b03df4) @@ -49,10 +49,10 @@ TSubTaskBase::ESubOperationResult HandleReadError(TOverlappedDataBuffer& rBuffer, bool& bSkip); TSubTaskBase::ESubOperationResult HandleWriteError(TOverlappedDataBuffer& rBuffer, bool& bSkip); - bool IsFreshlyCreated() const { return m_spFile->IsFreshlyCreated(); } - TSmartPath GetFilePath() const { return m_spFile->GetFilePath(); } - file_size_t GetFileSize() const { return m_spFile->GetFileSize(); } - file_size_t GetSeekPositionForResume(file_size_t fsLastAvailablePosition) { return m_spFile->GetSeekPositionForResume(fsLastAvailablePosition); } + bool IsFreshlyCreated() const; + TSmartPath GetFilePath() const; + TSubTaskBase::ESubOperationResult GetFileSize(file_size_t& fsSize, bool& bSkip) const; + file_size_t GetSeekPositionForResume(file_size_t fsLastAvailablePosition); bool IsOpen() const { return m_spFile->IsOpen(); } void Close() { m_spFile->Close(); } Index: src/libchcore/TLocalFilesystemFile.cpp =================================================================== diff -u -r789d0908abf8db57e27cfeac7045d9962f4b522a -ra0de3c317cb73a42ed4efbdf29b3a87243b03df4 --- src/libchcore/TLocalFilesystemFile.cpp (.../TLocalFilesystemFile.cpp) (revision 789d0908abf8db57e27cfeac7045d9962f4b522a) +++ src/libchcore/TLocalFilesystemFile.cpp (.../TLocalFilesystemFile.cpp) (revision a0de3c317cb73a42ed4efbdf29b3a87243b03df4) @@ -154,7 +154,7 @@ DWORD dwLastError = GetLastError(); LOG_ERROR(m_spLog) << "OpenExistingForWriting failed with error: " << dwLastError << GetFileInfoForLog(bNoBuffering); - throw TFileException(eErr_CannotOpenFile, dwLastError, m_pathFile, L"Cannot open for reading.", LOCATION); + throw TFileException(eErr_CannotOpenFile, dwLastError, m_pathFile, L"Cannot open for writing.", LOCATION); } LOG_DEBUG(m_spLog) << "OpenExistingForWriting succeeded. New handle: " << m_hFile << GetFileInfoForLog(bNoBuffering); } Index: src/libchcore/TOverlappedWriterFB.cpp =================================================================== diff -u -re7ca9e2c6306cd94e5e5caecc9cfdb3b562d3cdf -ra0de3c317cb73a42ed4efbdf29b3a87243b03df4 --- src/libchcore/TOverlappedWriterFB.cpp (.../TOverlappedWriterFB.cpp) (revision e7ca9e2c6306cd94e5e5caecc9cfdb3b562d3cdf) +++ src/libchcore/TOverlappedWriterFB.cpp (.../TOverlappedWriterFB.cpp) (revision a0de3c317cb73a42ed4efbdf29b3a87243b03df4) @@ -129,7 +129,8 @@ if(m_bReleaseMode) { - AdjustProcessedSize(fsWritten); + bool bSkip = false; + AdjustProcessedSize(fsWritten, bSkip); // ignore return value as we're already in release mode m_spEmptyBuffers->Push(pBuffer); bProcessedFlag = pBuffer->IsLastPart() && (pBuffer->GetBytesTransferred() == fsWritten); @@ -161,17 +162,46 @@ } // in case we read past the original eof, try to get new file size from filesystem - AdjustProcessedSize(fsWritten); + bool bSkip = false; + eResult = AdjustProcessedSize(fsWritten, bSkip); + if(eResult != TSubTaskBase::eSubResult_Continue) + { + m_spEmptyBuffers->Push(pBuffer); + bStopProcessing = true; + return eResult; + } + else if(bSkip) + { + m_spEmptyBuffers->Push(pBuffer); + bProcessedFlag = false; + bStopProcessing = true; + return eResult; + } + // stop iterating through file bStopProcessing = pBuffer->IsLastPart(); if(bStopProcessing) { m_spWriter->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(); + eResult = AdjustFinalSize(bSkip); + if(eResult != TSubTaskBase::eSubResult_Continue) + { + m_spEmptyBuffers->Push(pBuffer); + bStopProcessing = true; + return eResult; + } + else if(bSkip) + { + m_spEmptyBuffers->Push(pBuffer); + bProcessedFlag = false; + bStopProcessing = true; + return eResult; + } + bProcessedFlag = true; m_spStats->ResetCurrentItemProcessedSize(); } @@ -180,12 +210,18 @@ return eResult; } - void TOverlappedWriterFB::AdjustProcessedSize(file_size_t fsWritten) + TSubTaskBase::ESubOperationResult TOverlappedWriterFB::AdjustProcessedSize(file_size_t fsWritten, bool& bSkip) { + TSubTaskBase::ESubOperationResult eResult = TSubTaskBase::eSubResult_Continue; + // in case we read past the original eof, try to get new file size from filesystem if(m_spStats->WillAdjustProcessedSizeExceedTotalSize(0, fsWritten)) { - file_size_t fsNewSize = m_spSrcFile->GetFileSize(); + file_size_t fsNewSize = 0; + eResult = m_spSrcFile->GetFileSize(fsNewSize, bSkip); + if(eResult != TSubTaskBase::eSubResult_Continue || bSkip) + return eResult; + if(fsNewSize == m_spSrcFileInfo->GetLength64()) throw TCoreException(eErr_InternalProblem, L"Read more data from file than it really contained. Possible destination file corruption.", LOCATION); @@ -194,15 +230,23 @@ } m_spStats->AdjustProcessedSize(0, fsWritten); + + return eResult; } - void TOverlappedWriterFB::AdjustFinalSize() + TSubTaskBase::ESubOperationResult TOverlappedWriterFB::AdjustFinalSize(bool& bSkip) { + TSubTaskBase::ESubOperationResult eResult = TSubTaskBase::eSubResult_Continue; + unsigned long long ullCITotalSize = m_spStats->GetCurrentItemTotalSize(); unsigned long long ullCIProcessedSize = m_spStats->GetCurrentItemProcessedSize(); if(ullCIProcessedSize < ullCITotalSize) { - file_size_t fsNewSize = m_spSrcFile->GetFileSize(); + file_size_t fsNewSize = 0; + eResult = m_spSrcFile->GetFileSize(fsNewSize, bSkip); + if(eResult != TSubTaskBase::eSubResult_Continue || bSkip) + return eResult; + if(fsNewSize == m_spSrcFileInfo->GetLength64()) throw TCoreException(eErr_InternalProblem, L"Read less data from file than it really contained. Possible destination file corruption.", LOCATION); @@ -212,5 +256,7 @@ m_spStats->AdjustTotalSize(ullCITotalSize, fsNewSize); m_spSrcFileInfo->SetLength64(fsNewSize); } + + return eResult; } } Index: src/libchcore/TOverlappedWriterFB.h =================================================================== diff -u -r980c1a0de537813728871676200a0960410b11fb -ra0de3c317cb73a42ed4efbdf29b3a87243b03df4 --- src/libchcore/TOverlappedWriterFB.h (.../TOverlappedWriterFB.h) (revision 980c1a0de537813728871676200a0960410b11fb) +++ src/libchcore/TOverlappedWriterFB.h (.../TOverlappedWriterFB.h) (revision a0de3c317cb73a42ed4efbdf29b3a87243b03df4) @@ -42,8 +42,8 @@ TSubTaskBase::ESubOperationResult OnWriteFinished(bool& bStopProcessing, bool& bProcessedFlag); private: - void AdjustProcessedSize(file_size_t fsWritten); - void AdjustFinalSize(); + TSubTaskBase::ESubOperationResult AdjustProcessedSize(file_size_t fsWritten, bool& bSkip); + TSubTaskBase::ESubOperationResult AdjustFinalSize(bool& bSkip); private: TOverlappedWriterPtr m_spWriter; Index: src/libchcore/TSubTaskCopyMove.cpp =================================================================== diff -u -r276cada7cd66591ca5e5039acc24591d64fd8ae1 -ra0de3c317cb73a42ed4efbdf29b3a87243b03df4 --- src/libchcore/TSubTaskCopyMove.cpp (.../TSubTaskCopyMove.cpp) (revision 276cada7cd66591ca5e5039acc24591d64fd8ae1) +++ src/libchcore/TSubTaskCopyMove.cpp (.../TSubTaskCopyMove.cpp) (revision a0de3c317cb73a42ed4efbdf29b3a87243b03df4) @@ -406,7 +406,17 @@ // NOTE2: the by-chunk corrections of stats are still applied when copying to ensure even further size // matching; this update however still allows for better serialization management. file_size_t fsOldSize = pData->spSrcFile->GetLength64(); - file_size_t fsNewSize = rSrcFile.GetFileSize(); + file_size_t fsNewSize = 0; + + eResult = rSrcFile.GetFileSize(fsNewSize, bSkip); + if(eResult != eSubResult_Continue) + return eResult; + else if(bSkip) + { + pData->bProcessed = false; + return eSubResult_Continue; + } + if(fsNewSize != fsOldSize) { m_spSubTaskStats->AdjustTotalSize(fsOldSize, fsNewSize); @@ -418,20 +428,29 @@ unsigned long long ullSeekTo = ullProcessedSize; bool bDstFileFreshlyCreated = rDstFile.IsFreshlyCreated(); - unsigned long long ullDstFileSize = rDstFile.GetFileSize(); + file_size_t fsDstFileSize = 0; + eResult = rDstFile.GetFileSize(fsDstFileSize, bSkip); + if(eResult != eSubResult_Continue) + return eResult; + else if(bSkip) + { + pData->bProcessed = false; + return eSubResult_Continue; + } + // try to resume if possible bool bCanSilentResume = false; if (m_spSubTaskStats->CanCurrentItemSilentResume()) { - if(ullDstFileSize == ullProcessedSize && ullDstFileSize <= fsNewSize) + if(fsDstFileSize == ullProcessedSize && fsDstFileSize <= fsNewSize) { - ullSeekTo = ullDstFileSize; + ullSeekTo = fsDstFileSize; bCanSilentResume = true; } } - if(!bCanSilentResume && !bDstFileFreshlyCreated && ullDstFileSize > 0) + if(!bCanSilentResume && !bDstFileFreshlyCreated && fsDstFileSize > 0) { bool bShouldAppend = false; eResult = rDstFile.HandleFileAlreadyExistsFB(pData->spSrcFile, bShouldAppend, bSkip); @@ -444,7 +463,7 @@ } if(bShouldAppend) - ullSeekTo = std::min(ullDstFileSize, fsNewSize); + ullSeekTo = std::min(fsDstFileSize, fsNewSize); else ullSeekTo = 0; }