Index: src/libchcore/TOverlappedDataBuffer.h =================================================================== diff -u -r1506d51ff1c0a5d156dab398051efc0c87473e81 -re0588f4598dea526e0869360a0f5ee278e7902a0 --- src/libchcore/TOverlappedDataBuffer.h (.../TOverlappedDataBuffer.h) (revision 1506d51ff1c0a5d156dab398051efc0c87473e81) +++ src/libchcore/TOverlappedDataBuffer.h (.../TOverlappedDataBuffer.h) (revision e0588f4598dea526e0869360a0f5ee278e7902a0) @@ -58,6 +58,7 @@ DWORD GetErrorCode() const { return m_dwErrorCode; } void SetErrorCode(DWORD dwErrorCode) { m_dwErrorCode = dwErrorCode; } + bool HasError() const { return m_dwErrorCode != ERROR_SUCCESS; } // OVERLAPPED interface ULONG_PTR GetStatusCode() const { return Internal; } Index: src/libchcore/TOverlappedReaderWriter.cpp =================================================================== diff -u -r1506d51ff1c0a5d156dab398051efc0c87473e81 -re0588f4598dea526e0869360a0f5ee278e7902a0 --- src/libchcore/TOverlappedReaderWriter.cpp (.../TOverlappedReaderWriter.cpp) (revision 1506d51ff1c0a5d156dab398051efc0c87473e81) +++ src/libchcore/TOverlappedReaderWriter.cpp (.../TOverlappedReaderWriter.cpp) (revision e0588f4598dea526e0869360a0f5ee278e7902a0) @@ -37,8 +37,8 @@ m_bDataWritingFinished(false), m_dwDataChunkSize(dwChunkSize), m_ullNextReadBufferOrder(ullFilePos), - m_ullNextWriteBufferOrder(0), - m_ullNextFinishedBufferOrder(0) + m_ullNextWriteBufferOrder(ullFilePos), + m_ullNextFinishedBufferOrder(ullFilePos) { if(!spMemoryPool) throw TCoreException(eErr_InvalidArgument, L"spMemoryPool", LOCATION); @@ -121,7 +121,7 @@ m_setFullBuffers.erase(m_setFullBuffers.begin()); - if(pBuffer->GetErrorCode() == ERROR_SUCCESS) + if(!pBuffer->HasError()) { // if this is the last part - mark that writing is finished, so that no other buffer will be written if(pBuffer->IsLastPart()) @@ -144,6 +144,42 @@ if (!pBuffer) throw TCoreException(eErr_InvalidPointer, L"pBuffer", LOCATION); + if(pBuffer->HasError()) + { + if(pBuffer->GetFilePosition() < m_ullReadErrorOrder) + { + // case: new buffer failed at even earlier position in file than the one that failed previously (should also work for numeric_limits::max()) + // - move existing buffers with errors to failed read buffers, add current one to full queue + m_ullReadErrorOrder = pBuffer->GetFilePosition(); + + TOrderedBufferQueue newQueue; + + for(TOverlappedDataBuffer* pBuf : m_setFullBuffers) + { + if(pBuf->HasError()) + AddFailedReadBuffer(pBuf); + else + newQueue.insert(pBuf); + } + + if(newQueue.size() != m_setFullBuffers.size()) + std::swap(m_setFullBuffers, newQueue); + } + else if(pBuffer->GetFilePosition() > m_ullReadErrorOrder) + { + // case: new buffer failed at position later than the one that failed before - add to failed buffers + // for retry + AddFailedReadBuffer(pBuffer); + return; + } + //else -> case: we've received the same buffer that failed before; add to normal full queue for user to handle that + } + else if(m_ullReadErrorOrder == pBuffer->GetFilePosition()) + { + // case: adding correctly read buffer that previously failed to read; clear the error flag and add full buffer + m_ullReadErrorOrder = NoIoError; + } + LOG_TRACE(m_spLog) << L"Queuing buffer as full; buffer-order: " << pBuffer->GetFilePosition() << L", requested-data-size: " << pBuffer->GetRequestedDataSize() << L", real-data-size: " << pBuffer->GetRealDataSize() << Index: src/libchcore/TOverlappedReaderWriter.h =================================================================== diff -u -r1506d51ff1c0a5d156dab398051efc0c87473e81 -re0588f4598dea526e0869360a0f5ee278e7902a0 --- src/libchcore/TOverlappedReaderWriter.h (.../TOverlappedReaderWriter.h) (revision 1506d51ff1c0a5d156dab398051efc0c87473e81) +++ src/libchcore/TOverlappedReaderWriter.h (.../TOverlappedReaderWriter.h) (revision e0588f4598dea526e0869360a0f5ee278e7902a0) @@ -30,6 +30,9 @@ { class TOverlappedReaderWriter { + private: + static const unsigned long long NoIoError = 0xffffffffffffffff; + public: explicit TOverlappedReaderWriter(const logger::TLogFileDataPtr& spLogFileData, const TOverlappedMemoryPoolPtr& spBuffers, file_size_t ullFilePos, DWORD dwChunkSize); @@ -88,6 +91,8 @@ DWORD m_dwDataChunkSize = 0; unsigned long long m_ullNextReadBufferOrder = 0; // next order id for read buffers + unsigned long long m_ullReadErrorOrder = NoIoError; + unsigned long long m_ullNextWriteBufferOrder = 0; // next order id to be processed when writing unsigned long long m_ullNextFinishedBufferOrder = 0; // next order id to be processed when finishing writing Index: src/libchcore/TSubTaskCopyMove.cpp =================================================================== diff -u -r1506d51ff1c0a5d156dab398051efc0c87473e81 -re0588f4598dea526e0869360a0f5ee278e7902a0 --- src/libchcore/TSubTaskCopyMove.cpp (.../TSubTaskCopyMove.cpp) (revision 1506d51ff1c0a5d156dab398051efc0c87473e81) +++ src/libchcore/TSubTaskCopyMove.cpp (.../TSubTaskCopyMove.cpp) (revision e0588f4598dea526e0869360a0f5ee278e7902a0) @@ -445,7 +445,7 @@ throw TCoreException(eErr_InternalProblem, L"Write was possible, but no buffer is available", LOCATION); // was there an error reported? - if(pBuffer->GetErrorCode() != ERROR_SUCCESS) + if(pBuffer->HasError()) { // read error encountered - handle it eResult = HandleReadError(spFeedbackHandler, *pBuffer, pData->spSrcFile->GetFullFilePath(), bSkip); @@ -496,7 +496,7 @@ if (!pBuffer) throw TCoreException(eErr_InternalProblem, L"Write finished was possible, but no buffer is available", LOCATION); - if(pBuffer->GetErrorCode() != ERROR_SUCCESS) + if(pBuffer->HasError()) { eResult = HandleWriteError(spFeedbackHandler, *pBuffer, pData->pathDstFile, bSkip); if(eResult == TSubTaskBase::eSubResult_Retry)