Example #1
0
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;
}