Index: src/libchcore/TOverlappedDataBuffer.cpp =================================================================== diff -u -rb75259a9158d8b46d747e20ab4960dd002adb4b1 -refe016ef1d0cb0cf1ba379dbe3693e35f6a2361e --- src/libchcore/TOverlappedDataBuffer.cpp (.../TOverlappedDataBuffer.cpp) (revision b75259a9158d8b46d747e20ab4960dd002adb4b1) +++ src/libchcore/TOverlappedDataBuffer.cpp (.../TOverlappedDataBuffer.cpp) (revision efe016ef1d0cb0cf1ba379dbe3693e35f6a2361e) @@ -28,6 +28,7 @@ #include "IOverlappedDataBufferQueue.h" #include "RoundingFunctions.h" #include +#include #define STATUS_END_OF_FILE 0xc0000011 @@ -38,31 +39,29 @@ VOID CALLBACK OverlappedReadCompleted(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped) { TOverlappedDataBuffer* pBuffer = (TOverlappedDataBuffer*) lpOverlapped; - ATLTRACE(_T("OverlappedReadCompleted - read %I64u bytes\n"), pBuffer->GetBytesTransferred()); + // determine if this is the last packet bool bEof = (dwErrorCode == ERROR_HANDLE_EOF || pBuffer->GetStatusCode() == STATUS_END_OF_FILE || (dwErrorCode == ERROR_SUCCESS && pBuffer->GetBytesTransferred() != pBuffer->GetRequestedDataSize())); + // reset status code and error code if they pointed out to EOF if (pBuffer->GetStatusCode() == STATUS_END_OF_FILE) pBuffer->SetStatusCode(0); + pBuffer->SetErrorCode(dwErrorCode == ERROR_HANDLE_EOF ? ERROR_SUCCESS : dwErrorCode); - if (dwErrorCode != ERROR_SUCCESS) - ATLTRACE(_T("OverlappedReadCompleted error: %lu, status code: %I64u\n"), dwErrorCode, pBuffer->GetStatusCode()); - pBuffer->SetRealDataSize(dwNumberOfBytesTransfered); pBuffer->SetLastPart(bEof); + pBuffer->RequeueAsFull(); } VOID CALLBACK OverlappedWriteCompleted(DWORD dwErrorCode, DWORD /*dwNumberOfBytesTransfered*/, LPOVERLAPPED lpOverlapped) { TOverlappedDataBuffer* pBuffer = (TOverlappedDataBuffer*) lpOverlapped; - ATLTRACE(_T("OverlappedWriteCompleted - written %I64u bytes\n"), pBuffer->GetBytesTransferred()); - if(dwErrorCode != ERROR_SUCCESS) - ATLTRACE(_T("OverlappedWriteCompleted error: %lu, status code: %I64u\n"), dwErrorCode, pBuffer->GetStatusCode()); + pBuffer->SetErrorCode(dwErrorCode); pBuffer->RequeueAsFinished(); } @@ -136,4 +135,33 @@ m_pQueue->AddFinishedBuffer(this); } +void TOverlappedDataBuffer::InitForRead(unsigned long long ullPosition, DWORD dwRequestedSize) +{ + SetRequestedDataSize(dwRequestedSize); + SetFilePosition(ullPosition); + SetRealDataSize(0); + SetLastPart(false); + SetErrorCode(ERROR_SUCCESS); + SetStatusCode(0); + SetBytesTransferred(0); +} + +void TOverlappedDataBuffer::InitForWrite() +{ + SetErrorCode(ERROR_SUCCESS); + SetStatusCode(0); + SetBytesTransferred(0); +} + +void TOverlappedDataBuffer::Reset() +{ + SetRequestedDataSize(0); + SetFilePosition(0); + SetRealDataSize(0); + SetLastPart(false); + SetErrorCode(ERROR_SUCCESS); + SetStatusCode(0); + SetBytesTransferred(0); +} + END_CHCORE_NAMESPACE Index: src/libchcore/TOverlappedDataBuffer.h =================================================================== diff -u -rb75259a9158d8b46d747e20ab4960dd002adb4b1 -refe016ef1d0cb0cf1ba379dbe3693e35f6a2361e --- src/libchcore/TOverlappedDataBuffer.h (.../TOverlappedDataBuffer.h) (revision b75259a9158d8b46d747e20ab4960dd002adb4b1) +++ src/libchcore/TOverlappedDataBuffer.h (.../TOverlappedDataBuffer.h) (revision efe016ef1d0cb0cf1ba379dbe3693e35f6a2361e) @@ -47,40 +47,48 @@ TOverlappedDataBuffer& operator=(TOverlappedDataBuffer&& rSrc) = delete; // interface methods + // buffer size management void ReinitializeBuffer(size_t stNewBufferSize); LPVOID GetBufferPtr(); size_t GetBufferSize() const { return m_stBufferSize; } + // members DWORD GetRequestedDataSize() const { return m_dwRequestedDataSize; } - void SetRequestedDataSize(DWORD val) { m_dwRequestedDataSize = val; } + void SetRequestedDataSize(DWORD dwRequestedSize) { m_dwRequestedDataSize = dwRequestedSize; } + DWORD GetRealDataSize() const { return m_dwRealDataSize; } + void SetRealDataSize(DWORD dwRealDataSize) { m_dwRealDataSize = dwRealDataSize; } + void SetLastPart(bool bLastPart) { m_bLastPart = bLastPart; } bool IsLastPart() const { return m_bLastPart; } - void RequeueAsEmpty(); - void RequeueAsFull(); - void RequeueAsFinished(); + unsigned long long GetBufferOrder() const { return m_ullBufferOrder; } + void SetBufferOrder(unsigned long long ullOrder) { m_ullBufferOrder = ullOrder; } + DWORD GetErrorCode() const { return m_dwErrorCode; } + void SetErrorCode(DWORD dwErrorCode) { m_dwErrorCode = dwErrorCode; } + // OVERLAPPED interface ULONG_PTR GetStatusCode() const { return Internal; } void SetStatusCode(ULONG_PTR ulStatusCode) { Internal = ulStatusCode; } - DWORD GetErrorCode() const { return m_dwErrorCode; } - void SetErrorCode(DWORD dwErrorCode) { m_dwErrorCode = dwErrorCode; } - void SetBytesTransferred(ULONG_PTR ulBytes) { InternalHigh = ulBytes; } ULONG_PTR GetBytesTransferred() const { return InternalHigh; } - DWORD GetRealDataSize() const { return m_dwRealDataSize; } - void SetRealDataSize(DWORD dwRealDataSize) { m_dwRealDataSize = dwRealDataSize; } - unsigned long long GetFilePosition() const { return (unsigned long long)OffsetHigh << 32 | Offset; } void SetFilePosition(unsigned long long ullPosition) { OffsetHigh = (DWORD) (ullPosition >> 32); Offset = (DWORD) ullPosition; } - unsigned long long GetBufferOrder() const { return m_ullBufferOrder; } - void SetBufferOrder(unsigned long long ullOrder) { m_ullBufferOrder = ullOrder; } + // queue management + void RequeueAsEmpty(); + void RequeueAsFull(); + void RequeueAsFinished(); + // composite initialization + void InitForRead(unsigned long long ullPosition, DWORD dwRequestedSize); + void InitForWrite(); + void Reset(); + private: void ReleaseBuffer(); Index: src/libchcore/TOverlappedDataBufferQueue.cpp =================================================================== diff -u -r9312d2ac24e7963495b234adb8b9628076b16023 -refe016ef1d0cb0cf1ba379dbe3693e35f6a2361e --- src/libchcore/TOverlappedDataBufferQueue.cpp (.../TOverlappedDataBufferQueue.cpp) (revision 9312d2ac24e7963495b234adb8b9628076b16023) +++ src/libchcore/TOverlappedDataBufferQueue.cpp (.../TOverlappedDataBufferQueue.cpp) (revision efe016ef1d0cb0cf1ba379dbe3693e35f6a2361e) @@ -30,7 +30,7 @@ } TOverlappedDataBufferQueue::TOverlappedDataBufferQueue() : - m_eventReadPossible(true, true), + m_eventReadPossible(true, false), m_eventWritePossible(true, false), m_eventWriteFinished(true, false), m_stBufferSize(0), @@ -43,7 +43,7 @@ } TOverlappedDataBufferQueue::TOverlappedDataBufferQueue(size_t stCount, size_t stBufferSize) : - m_eventReadPossible(true, true), + m_eventReadPossible(true, false), m_eventWritePossible(true, false), m_eventWriteFinished(true, false), m_stBufferSize(0), @@ -226,6 +226,7 @@ m_listEmptyBuffers.push_back(upElement.get()); } + UpdateReadPossibleEvent(); return; } @@ -238,6 +239,7 @@ } m_stBufferSize = stCount; + UpdateReadPossibleEvent(); } void TOverlappedDataBufferQueue::DataSourceChanged() Index: src/libchcore/TSubTaskCopyMove.cpp =================================================================== diff -u -rb75259a9158d8b46d747e20ab4960dd002adb4b1 -refe016ef1d0cb0cf1ba379dbe3693e35f6a2361e --- src/libchcore/TSubTaskCopyMove.cpp (.../TSubTaskCopyMove.cpp) (revision b75259a9158d8b46d747e20ab4960dd002adb4b1) +++ src/libchcore/TSubTaskCopyMove.cpp (.../TSubTaskCopyMove.cpp) (revision efe016ef1d0cb0cf1ba379dbe3693e35f6a2361e) @@ -335,12 +335,10 @@ case WAIT_OBJECT_0 + eReadPossible: { TOverlappedDataBuffer* pBuffer = pData->dbBuffer.GetEmptyBuffer(); - ATLTRACE(_T("Read possible with buffer %p\n"), pBuffer); if (!pBuffer) THROW_CORE_EXCEPTION(eErr_InternalProblem); - pBuffer->SetFilePosition(ullNextReadPos); - pBuffer->SetRequestedDataSize(dwToRead); + pBuffer->InitForRead(ullNextReadPos, dwToRead); ullNextReadPos += dwToRead; eResult = ReadFileFB(spFeedbackHandler, fileSrc, *pBuffer, pData->spSrcFile->GetFullFilePath(), bSkip); @@ -360,7 +358,6 @@ case WAIT_OBJECT_0 + eWritePossible: { TOverlappedDataBuffer* pBuffer = pData->dbBuffer.GetFullBuffer(); - ATLTRACE(_T("Write possible with buffer %p\n"), pBuffer); if (!pBuffer) THROW_CORE_EXCEPTION(eErr_InternalProblem); @@ -399,6 +396,8 @@ } else { + pBuffer->InitForWrite(); + eResult = WriteFileFB(spFeedbackHandler, fileDst, *pBuffer, pData->pathDstFile, bSkip); if(eResult != TSubTaskBase::eSubResult_Continue) return eResult; @@ -419,7 +418,6 @@ case WAIT_OBJECT_0 + eWriteFinished: { TOverlappedDataBuffer* pBuffer = pData->dbBuffer.GetFinishedBuffer(); - ATLTRACE(_T("Write finished with buffer %p\n"), pBuffer); if (!pBuffer) THROW_CORE_EXCEPTION(eErr_InternalProblem); Index: src/libchcore/Tests/TOverlappedDataBufferQueueTests.cpp =================================================================== diff -u --- src/libchcore/Tests/TOverlappedDataBufferQueueTests.cpp (revision 0) +++ src/libchcore/Tests/TOverlappedDataBufferQueueTests.cpp (revision efe016ef1d0cb0cf1ba379dbe3693e35f6a2361e) @@ -0,0 +1,112 @@ +#include "stdafx.h" +#include "gtest/gtest.h" +#include "gmock/gmock.h" +#include "../TOverlappedDataBufferQueue.h" +#include "../TOverlappedDataBuffer.h" + +using namespace chcore; + +TEST(TOverlappedDataBufferQueueTests, DefaultConstructor_SanityTest) +{ + TOverlappedDataBufferQueue queue; + + EXPECT_EQ(nullptr, queue.GetEmptyBuffer()); + EXPECT_EQ(nullptr, queue.GetFullBuffer()); + EXPECT_EQ(nullptr, queue.GetFinishedBuffer()); + + EXPECT_NE(nullptr, queue.GetEventReadPossibleHandle()); + EXPECT_NE(nullptr, queue.GetEventWritePossibleHandle()); + EXPECT_NE(nullptr, queue.GetEventWriteFinishedHandle()); + + DWORD dwResult = WaitForSingleObject(queue.GetEventReadPossibleHandle(), 0); + EXPECT_EQ(WAIT_TIMEOUT, dwResult); + + dwResult = WaitForSingleObject(queue.GetEventWritePossibleHandle(), 0); + EXPECT_EQ(WAIT_TIMEOUT, dwResult); + + dwResult = WaitForSingleObject(queue.GetEventWriteFinishedHandle(), 0); + EXPECT_EQ(WAIT_TIMEOUT, dwResult); +} + +TEST(TOverlappedDataBufferQueueTests, AllocatingConstructor_SanityTest) +{ + TOverlappedDataBufferQueue queue(3, 32768); + + EXPECT_NE(nullptr, queue.GetEmptyBuffer()); + EXPECT_EQ(nullptr, queue.GetFullBuffer()); + EXPECT_EQ(nullptr, queue.GetFinishedBuffer()); + + EXPECT_NE(nullptr, queue.GetEventReadPossibleHandle()); + EXPECT_NE(nullptr, queue.GetEventWritePossibleHandle()); + EXPECT_NE(nullptr, queue.GetEventWriteFinishedHandle()); + + DWORD dwResult = WaitForSingleObject(queue.GetEventReadPossibleHandle(), 0); + EXPECT_EQ(WAIT_OBJECT_0 + 0, dwResult); + + dwResult = WaitForSingleObject(queue.GetEventWritePossibleHandle(), 0); + EXPECT_EQ(WAIT_TIMEOUT, dwResult); + + dwResult = WaitForSingleObject(queue.GetEventWriteFinishedHandle(), 0); + EXPECT_EQ(WAIT_TIMEOUT, dwResult); +} + +TEST(TOverlappedDataBufferQueueTests, GetEmptyBuffer) +{ + TOverlappedDataBufferQueue queue(3, 32768); + + DWORD dwResult = WaitForSingleObject(queue.GetEventReadPossibleHandle(), 0); + EXPECT_EQ(WAIT_OBJECT_0 + 0, dwResult); + + EXPECT_NE(nullptr, queue.GetEmptyBuffer()); + dwResult = WaitForSingleObject(queue.GetEventReadPossibleHandle(), 0); + EXPECT_EQ(WAIT_OBJECT_0 + 0, dwResult); + + EXPECT_NE(nullptr, queue.GetEmptyBuffer()); + dwResult = WaitForSingleObject(queue.GetEventReadPossibleHandle(), 0); + EXPECT_EQ(WAIT_OBJECT_0 + 0, dwResult); + + EXPECT_NE(nullptr, queue.GetEmptyBuffer()); + dwResult = WaitForSingleObject(queue.GetEventReadPossibleHandle(), 0); + EXPECT_EQ(WAIT_TIMEOUT, dwResult); + + EXPECT_EQ(nullptr, queue.GetEmptyBuffer()); +} + +TEST(TOverlappedDataBufferQueueTests, AddEmptyBuffer) +{ + TOverlappedDataBufferQueue queue(3, 32768); + + TOverlappedDataBuffer* pBuffers[3] = { queue.GetEmptyBuffer(), queue.GetEmptyBuffer(), queue.GetEmptyBuffer() }; + + DWORD dwResult = WaitForSingleObject(queue.GetEventReadPossibleHandle(), 0); + EXPECT_EQ(WAIT_TIMEOUT, dwResult); + + queue.AddEmptyBuffer(pBuffers[0]); + dwResult = WaitForSingleObject(queue.GetEventReadPossibleHandle(), 0); + EXPECT_EQ(WAIT_OBJECT_0 + 0, dwResult); + + queue.AddEmptyBuffer(pBuffers[1]); + dwResult = WaitForSingleObject(queue.GetEventReadPossibleHandle(), 0); + EXPECT_EQ(WAIT_OBJECT_0 + 0, dwResult); + + queue.AddEmptyBuffer(pBuffers[2]); + dwResult = WaitForSingleObject(queue.GetEventReadPossibleHandle(), 0); + EXPECT_EQ(WAIT_OBJECT_0 + 0, dwResult); +} + +TEST(TOverlappedDataBufferQueueTests, GetFullBuffer_AddFullBuffer) +{ + TOverlappedDataBufferQueue queue(3, 32768); + + TOverlappedDataBuffer* pBuffers[3] = { queue.GetEmptyBuffer(), queue.GetEmptyBuffer(), queue.GetEmptyBuffer() }; + + TOverlappedDataBuffer* pBuffer = pBuffers[0]; + + pBuffer->InitForRead(0, 1230); + pBuffer->SetBytesTransferred(1230); + pBuffer->SetStatusCode(0); + + queue.AddFullBuffer(pBuffer); + DWORD dwResult = WaitForSingleObject(queue.GetEventWritePossibleHandle(), 0); + EXPECT_EQ(WAIT_OBJECT_0 + 0, dwResult); +} Index: src/libchcore/Tests/TOverlappedDataBufferTests.cpp =================================================================== diff -u --- src/libchcore/Tests/TOverlappedDataBufferTests.cpp (revision 0) +++ src/libchcore/Tests/TOverlappedDataBufferTests.cpp (revision efe016ef1d0cb0cf1ba379dbe3693e35f6a2361e) @@ -0,0 +1,12 @@ +#include "stdafx.h" +#include "gtest/gtest.h" +#include "gmock/gmock.h" +#include "../TOverlappedDataBuffer.h" +#include "../TCoreException.h" + +using namespace chcore; + +TEST(TOverlappedDataBufferTests, DefaultConstructor_InvalidInput) +{ + EXPECT_THROW(TOverlappedDataBuffer(0, nullptr), TCoreException); +} Index: src/libchcore/libchcore.vc120.vcxproj =================================================================== diff -u -r387751793d274e49253e796ca7cec4f3d0cf07a9 -refe016ef1d0cb0cf1ba379dbe3693e35f6a2361e --- src/libchcore/libchcore.vc120.vcxproj (.../libchcore.vc120.vcxproj) (revision 387751793d274e49253e796ca7cec4f3d0cf07a9) +++ src/libchcore/libchcore.vc120.vcxproj (.../libchcore.vc120.vcxproj) (revision efe016ef1d0cb0cf1ba379dbe3693e35f6a2361e) @@ -523,6 +523,7 @@ + @@ -686,6 +687,8 @@ true true + + Index: src/libchcore/libchcore.vc120.vcxproj.filters =================================================================== diff -u -r387751793d274e49253e796ca7cec4f3d0cf07a9 -refe016ef1d0cb0cf1ba379dbe3693e35f6a2361e --- src/libchcore/libchcore.vc120.vcxproj.filters (.../libchcore.vc120.vcxproj.filters) (revision 387751793d274e49253e796ca7cec4f3d0cf07a9) +++ src/libchcore/libchcore.vc120.vcxproj.filters (.../libchcore.vc120.vcxproj.filters) (revision efe016ef1d0cb0cf1ba379dbe3693e35f6a2361e) @@ -63,6 +63,9 @@ {202d13d3-126b-4811-8c1c-a14b4f0476b7} + + {49c9ae7e-1bc4-4875-8512-e92e0c00fb19} + @@ -365,6 +368,9 @@ Source Files\Tools + + Source Files\Tools\DebugTrace + @@ -664,5 +670,11 @@ Source Files\Tools + + Tests + + + Tests + \ No newline at end of file