VOID CNktDvTransportEngine::WorkerThreadProc(__in SIZE_T nIndex) { CConnection *lpConn; LPOVERLAPPED _lpOvr; CNktDvTransportOverlapped *lpOvr; HRESULT hRes; HANDLE hEventCopy; BOOL b, bReadPending; DWORD dwNumberOfBytes, dwWritten; lpCallback->TEC_WorkerThreadStarted(); //---- for (;;) { lpConn = NULL; lpOvr = NULL; b = ::GetQueuedCompletionStatus(hIOCP, &dwNumberOfBytes, (PULONG_PTR)&lpConn, &_lpOvr, INFINITE); if (lpConn == NULL) { break; //a completion key of 0 is posted to the iocp to request us to shut down... } hRes = (b != FALSE) ? S_OK : NKT_HRESULT_FROM_LASTERROR(); { CConnectionAutoRef cConnAutoRef(lpConn); lpOvr = CNktDvTransportOverlapped::ClassFromOverlapped(_lpOvr); bReadPending = FALSE; if (_lpOvr != NULL) { switch (lpOvr->dwType) { case XTYPE_Read: lpOvr->dwReadedBytes = dwNumberOfBytes; //add to read queue if (SUCCEEDED(hRes)) { lpConn->AddBufferInSortedReadedQueue(lpOvr); hRes = lpConn->SendReadPacket(); //setup read-ahead } NKT_DEBUGPRINTLNA(Nektra::dlTransport, ("%lu) TransportEngine[ReadCompleted]: Ovr=%IXh, " "hRes=%08X", ::GetTickCount(), lpOvr, hRes)); bReadPending = TRUE; break; case XTYPE_WriteRequest: { CNktAutoFastMutex cLock(lpConn); if (SUCCEEDED(hRes)) lpConn->AddBufferInSortedToWriteQueue(lpOvr); while (SUCCEEDED(hRes) && cShutdownMtx.IsSystemActive() != FALSE && cShutdownMtx.IsShuttingDown() == FALSE) { //get next sequenced block to write lpOvr = lpConn->GetBufferFromSortedToWriteQueue(lpConn->nNextWriteOrderToProcess); if (lpOvr == NULL) break; if (lpOvr->dwType != XTYPE_Discard) { lpConn->AddBufferToRwList(lpOvr); //do real write lpOvr->dwType = XTYPE_Write; if (lpOvr->sMsg.sMsgCommon.hProcessedEvent != NULL) { if (::DuplicateHandle(::GetCurrentProcess(), (HANDLE)(lpOvr->sMsg.sMsgCommon.hProcessedEvent), lpConn->hAgentProc, &hEventCopy, 0, FALSE, DUPLICATE_SAME_ACCESS) != FALSE) lpOvr->sMsg.sMsgCommon.hProcessedEvent = NKT_PTR_2_ULONGLONG(hEventCopy); else hRes = NKT_HRESULT_FROM_LASTERROR(); } if (SUCCEEDED(hRes)) { if (::WriteFile(lpConn->hPipe, &(lpOvr->sMsg), lpOvr->dwWrittenBytes, &dwWritten, &(lpOvr->sOvr)) == FALSE) { hRes = NKT_HRESULT_FROM_LASTERROR(); if (hRes == NKT_HRESULT_FROM_WIN32(ERROR_IO_PENDING)) hRes = S_OK; } } if (SUCCEEDED(hRes)) lpConn->AddRef(); else lpConn->FreeBuffer(lpOvr); NKT_DEBUGPRINTLNA(Nektra::dlTransport, ("%lu) TransportEngine[Write]: Ovr=%IXh, " "hRes=%08X", ::GetTickCount(), lpOvr, hRes)); } else { lpConn->FreeBuffer(lpOvr); } NktInterlockedIncrement(&(lpConn->nNextWriteOrderToProcess)); } } break; case XTYPE_Write: if (SUCCEEDED(hRes) && lpOvr->dwWrittenBytes != dwNumberOfBytes) hRes = NKT_HRESULT_FROM_WIN32(ERROR_WRITE_FAULT); NKT_DEBUGPRINTLNA(Nektra::dlTransport, ("%lu) TransportEngine[WriteCompleted]: Ovr=%IXh, " "hRes=%08X", ::GetTickCount(), lpOvr, hRes)); lpConn->FreeBuffer(lpOvr); break; case XTYPE_Discard: lpConn->FreeBuffer(lpOvr); break; default: NKT_ASSERT(FALSE); lpConn->FreeBuffer(lpOvr); break; } } else { hRes = NKT_DVERR_InvalidTransportData; } if (SUCCEEDED(hRes) && bReadPending != FALSE) { while (SUCCEEDED(hRes) && cShutdownMtx.IsSystemActive() != FALSE && cShutdownMtx.IsShuttingDown() == FALSE) { //get next sequenced block readed lpOvr = lpConn->GetBufferFromSortedReadedQueue(lpConn->nNextReadOrderToProcess); if (lpOvr == NULL) break; hRes = DispatchReadedMessage(lpConn, lpOvr); NktInterlockedIncrement(&(lpConn->nNextReadOrderToProcess)); } } if (FAILED(hRes)) { if (cShutdownMtx.IsSystemActive() != FALSE && cShutdownMtx.IsShuttingDown() == FALSE) lpCallback->TEC_OnTransportError(this, lpConn->dwPid, hRes); DisconnectAgent(lpConn->dwPid); } lpConn->Release(); } } //---- lpCallback->TEC_WorkerThreadEnded(); return; }