Index: src/libchengine/TOverlappedWriterFB.cpp =================================================================== diff -u -N -r08717141ce5f6926116c298cbc9442094a45bb67 -rb9453afbc6264bc3f3c6a7f86fadab7744e0fb16 --- src/libchengine/TOverlappedWriterFB.cpp (.../TOverlappedWriterFB.cpp) (revision 08717141ce5f6926116c298cbc9442094a45bb67) +++ src/libchengine/TOverlappedWriterFB.cpp (.../TOverlappedWriterFB.cpp) (revision b9453afbc6264bc3f3c6a7f86fadab7744e0fb16) @@ -33,7 +33,7 @@ TWorkerThreadController& rThreadController, const TSubTaskStatsInfoPtr& spStats, const TFileInfoPtr& spSrcFileInfo, - const TSmartPath& pathDst, + const TDestinationPathProvider& rDstPathProvider, const logger::TLogFileDataPtr& spLogFileData, const TOrderedBufferQueuePtr& spBuffersToWrite, const TOverlappedProcessorRangePtr& spRange, @@ -43,6 +43,7 @@ bool bNoBuffering, bool bProtectReadOnlyFiles, bool bUpdateFileAttributesAndTimes) : + m_counterOnTheFly(), m_spWriter(std::make_shared(spLogFileData, spBuffersToWrite, spRange, spEmptyBuffers, stMaxOtfBuffers, m_counterOnTheFly.GetSharedCount())), m_spStats(spStats), @@ -54,7 +55,13 @@ m_eventWritingFinished(true, false), m_eventLocalKill(true, false), m_rThreadController(rThreadController), - m_spLog(logger::MakeLogger(spLogFileData, L"File-Writer")) + m_spLog(logger::MakeLogger(spLogFileData, L"File-Writer")), + m_spFilesystem(spFilesystem), + m_rDstPathProvider(rDstPathProvider), + m_spFeedbackManager(spFeedbackManager), + m_spLogFileData(spLogFileData), + m_bNoBuffering(bNoBuffering), + m_bProtectReadOnlyFiles(bProtectReadOnlyFiles) { if(!spFilesystem) throw TCoreException(eErr_InvalidArgument, L"spFilesystem is NULL", LOCATION); @@ -72,9 +79,6 @@ throw TCoreException(eErr_InvalidArgument, L"spLogFileData is NULL", LOCATION); if(!spBuffersToWrite) throw TCoreException(eErr_InvalidArgument, L"spBuffersToWrite is NULL", LOCATION); - - IFilesystemFilePtr fileDst = spFilesystem->CreateFileObject(IFilesystemFile::eMode_Write, pathDst, bNoBuffering, bProtectReadOnlyFiles); - m_spDstFile = std::make_shared(fileDst, spFeedbackManager, spLogFileData, rThreadController, spFilesystem); } TOverlappedWriterFB::~TOverlappedWriterFB() @@ -219,50 +223,73 @@ TSubTaskBase::ESubOperationResult TOverlappedWriterFB::Start() { - // open destination file, handle the failures and possibly existence of the destination file unsigned long long ullProcessedSize = m_spStats->GetCurrentItemProcessedSize(); unsigned long long ullSeekTo = ullProcessedSize; - bool bDstFileFreshlyCreated = false; - TSubTaskBase::ESubOperationResult eResult = m_spDstFile->IsFreshlyCreated(bDstFileFreshlyCreated); - if(eResult != TSubTaskBase::eSubResult_Continue) - return eResult; + TSubTaskBase::ESubOperationResult eResult = TSubTaskBase::eSubResult_Continue; - file_size_t fsDstFileSize = 0; - eResult = m_spDstFile->GetFileSize(fsDstFileSize); - if(eResult != TSubTaskBase::eSubResult_Continue) - return eResult; - - // try to resume if possible - bool bCanSilentResume = false; - if(m_spStats->CanCurrentItemSilentResume()) + bool bRetryAfterRename = false; + do { - if(fsDstFileSize == ullProcessedSize && fsDstFileSize <= m_spSrcFileInfo->GetLength64()) + bRetryAfterRename = false; + + TSmartPath pathFullDst = m_rDstPathProvider.CalculateDestinationPath(m_spSrcFileInfo); + + IFilesystemFilePtr fileDst = m_spFilesystem->CreateFileObject(IFilesystemFile::eMode_Write, pathFullDst, m_bNoBuffering, m_bProtectReadOnlyFiles); + m_spDstFile = std::make_shared(fileDst, m_spFeedbackManager, m_spLogFileData, m_rThreadController, m_spFilesystem); + + // open destination file, handle the failures and possibly existence of the destination file + bDstFileFreshlyCreated = false; + eResult = m_spDstFile->IsFreshlyCreated(bDstFileFreshlyCreated); + if(eResult != TSubTaskBase::eSubResult_Continue) + return eResult; + + file_size_t fsDstFileSize = 0; + eResult = m_spDstFile->GetFileSize(fsDstFileSize); + if(eResult != TSubTaskBase::eSubResult_Continue) + return eResult; + + // try to resume if possible + bool bCanSilentResume = false; + if(m_spStats->CanCurrentItemSilentResume()) { - ullSeekTo = fsDstFileSize; - bCanSilentResume = true; + if(fsDstFileSize == ullProcessedSize && fsDstFileSize <= m_spSrcFileInfo->GetLength64()) + { + ullSeekTo = fsDstFileSize; + bCanSilentResume = true; + } + else if(fsDstFileSize > ullProcessedSize && fsDstFileSize - ullProcessedSize == IFilesystemFile::MaxSectorSize && + m_spSrcFileInfo->GetLength64() > ullProcessedSize && m_spSrcFileInfo->GetLength64() < fsDstFileSize) + { + // special case - resuming file that was not finalized completely last time + ullSeekTo = ullProcessedSize; + bCanSilentResume = true; + } } - else if(fsDstFileSize > ullProcessedSize && fsDstFileSize - ullProcessedSize == IFilesystemFile::MaxSectorSize && - m_spSrcFileInfo->GetLength64() > ullProcessedSize && m_spSrcFileInfo->GetLength64() < fsDstFileSize) + + if(!bCanSilentResume && !bDstFileFreshlyCreated && fsDstFileSize > 0) { - // special case - resuming file that was not finalized completely last time - ullSeekTo = ullProcessedSize; - bCanSilentResume = true; - } - } + bool bShouldAppend = false; + bool bShouldRename = false; - if(!bCanSilentResume && !bDstFileFreshlyCreated && fsDstFileSize > 0) - { - bool bShouldAppend = false; - eResult = m_spDstFile->HandleFileAlreadyExistsFB(m_spSrcFileInfo, bShouldAppend); - if(eResult != TSubTaskBase::eSubResult_Continue) - return eResult; + eResult = m_spDstFile->HandleFileAlreadyExistsFB(m_spSrcFileInfo, m_rDstPathProvider, bShouldAppend, bShouldRename); + if(eResult != TSubTaskBase::eSubResult_Continue) + return eResult; - if(bShouldAppend) - ullSeekTo = std::min(fsDstFileSize, m_spSrcFileInfo->GetLength64()); - else - ullSeekTo = 0; + if(bShouldRename) + { + bRetryAfterRename = true; + ullSeekTo = 0; + m_spDstFile->Close(); + m_spDstFile.reset(); + } + if(bShouldAppend) + ullSeekTo = std::min(fsDstFileSize, m_spSrcFileInfo->GetLength64()); + else + ullSeekTo = 0; + } } + while(bRetryAfterRename); if(m_bOnlyCreate) {