Example #1
0
HRESULT CNktDvTransportEngine::ConnectAgent(__in DWORD dwPid, __in DWORD dwTimeout)
{
  CNktDvShutdownAutoLock cSdLock(&cShutdownMtx);
  CNktDvAutoCancellableFastMutex cLock(this, &cShutdownMtx);
  CConnection *lpConn;
  HRESULT hRes;

  if (cLock.IsLockHeld() == FALSE || cShutdownMtx.IsShuttingDown() != FALSE)
    return NKT_DVERR_Cancelled;
  if (cShutdownMtx.IsSystemActive() == FALSE)
    return E_FAIL; //not initialized
  if (dwPid == 0 || dwPid == dwMePid)
    return E_INVALIDARG;
  //check if connection already exists
  {
    CConnectionAutoRef cConnAutoRef(lpConn = FindConnectionAndAddRef(dwPid), FALSE);

    if (lpConn != NULL)
      return NKT_DVERR_AlreadyExists;
  }
  //----
  lpConn = NKT_MEMMGR_NEW CConnection(this, dwPid);
  if (lpConn == NULL)
    return E_OUTOFMEMORY;
  //create pipe
  hRes = lpConn->Initialize(hIOCP, dwTimeout);
  if (FAILED(hRes))
  {
    lpConn->Release();
    return hRes;
  }
  //add to connection list
  cConnList.PushTail(lpConn);
  return S_OK;
}
Example #2
0
VOID CNktDvTransportEngine::DispatcherThreadProc(__in SIZE_T nDispatcherPtr)
{
#define MESSAGES_PER_ROUND 4
  CNktThread *lpThread;
  CNktDvTransportOverlapped *lpOvr[MESSAGES_PER_ROUND];
  HANDLE hAvailableEvent;
  DWORD dwHitEvent;
  CConnection *lpConn;
  SIZE_T nProcessed, k, nRetrieved;
  CDispatcher *lpDispatcher;
  HRESULT hRes;

  lpDispatcher = (CDispatcher*)nDispatcherPtr;
  //----
  lpCallback->TEC_WorkerThreadStarted();
  //----
  lpThread = &(lpDispatcher->cThread);
  hAvailableEvent = lpDispatcher->hEvent;
  while (1)
  {
    if (lpThread->CheckForAbort(INFINITE, 1, &hAvailableEvent, &dwHitEvent) != FALSE)
      break;
    if (dwHitEvent == 1)
    {
      ::ResetEvent(hAvailableEvent);
      //init working
      NktInterlockedExchange(&(lpDispatcher->nIsWorking), 1);
      while (lpThread->CheckForAbort(0) == FALSE)
      {
        {
          CNktAutoFastMutex cLock(lpDispatcher);

          lpOvr[0] = lpDispatcher->PeekNextOverlapped();
          if (lpOvr[0] == NULL)
            break;
          lpOvr[0]->RemoveNode(); //remove from list
          //try to get more messages
          for (nRetrieved=1; nRetrieved<MESSAGES_PER_ROUND; nRetrieved++)
          {
            lpOvr[nRetrieved] = lpDispatcher->PeekNextOverlapped();
            if (lpOvr[nRetrieved] == NULL ||
                lpOvr[nRetrieved]->sEngineInternals.lpConn != lpOvr[0]->sEngineInternals.lpConn ||
                lpOvr[nRetrieved]->sEngineInternals.dwThreadId != lpOvr[0]->sEngineInternals.dwThreadId)
              break;
            if (lpOvr[0]->sMsg.sMsgCommon.dwMsgCode == NKT_DV_TMSG_CODE_BigData)
            {
              if (lpOvr[nRetrieved]->sMsg.sMsgCommon.dwMsgCode != NKT_DV_TMSG_CODE_BigData)
                break;
            }
            else
            {
              if (lpOvr[nRetrieved]->sMsg.sMsgCommon.dwMsgCode == NKT_DV_TMSG_CODE_BigData)
                break;
            }
            lpOvr[nRetrieved]->RemoveNode(); //remove from list
          }
        }
        //at this point we have up to 'MESSAGES_PER_ROUND' messages to process of the same
        //connection/tid
        lpConn = (CConnection*)(lpOvr[0]->sEngineInternals.lpConn);
        hRes = S_OK;
        if (lpOvr[0]->sMsg.sMsgCommon.dwMsgCode == NKT_DV_TMSG_CODE_BigData)
        {
          CNktAutoFastMutex cConnAutoLock(lpConn);

          //try to process a sequence of "NKT_DV_TMSG_CODE_BigData" in the same round
          for (nProcessed=0; nProcessed<nRetrieved && SUCCEEDED(hRes); nProcessed++)
          {
            hRes = lpConn->cBigData->ProcessPacket(&(lpOvr[nProcessed]->sMsg.sMsgCommon));
            //signal client message event
            if (SUCCEEDED(hRes))
              hRes = SignalProcessedEvent(lpOvr[nProcessed]);
            //free buffer
            lpConn->FreeBuffer(lpOvr[nProcessed]);
          }
        }
        else
        {
          //try to process a sequence of standard packets
          for (nProcessed=0; nProcessed<nRetrieved && SUCCEEDED(hRes); nProcessed++)
          {
            //process
            hRes = lpCallback->TEC_OnAgentMessage(this, lpConn->dwPid,
                                                  &(lpOvr[nProcessed]->sMsg.sMsgCommon),
                                                  (SIZE_T)(lpOvr[nProcessed]->dwReadedBytes),
                                                  lpConn->hAgentProc, lpConn->cBigData);
            //signal client message event
            if (SUCCEEDED(hRes))
              hRes = SignalProcessedEvent(lpOvr[nProcessed]);
          }
          //free processed buffers
          {
            CNktAutoFastMutex cConnAutoLock(lpConn);

            for (k=0; k<nProcessed; k++)
              lpConn->FreeBuffer(lpOvr[k]);
          }
        }
        //if some packets were not processed, it is almost sure that it is because of an error
        if (nProcessed < nRetrieved)
        {
          //requeue non-processed buffers at the front
          CNktAutoFastMutex cLock(lpDispatcher);

          for (k=nRetrieved; k>nProcessed; )
            lpDispatcher->AddOverlapped(lpOvr[--k], TRUE);
        }
        //release connection one for each processed packet from the list
        for (k=0; k<nProcessed; k++)
          lpConn->Release();
        //handle errors
        if (FAILED(hRes))
        {
          if (cShutdownMtx.IsSystemActive() != FALSE && cShutdownMtx.IsShuttingDown() == FALSE)
            lpCallback->TEC_OnTransportError(this, lpConn->dwPid, hRes);
          DisconnectAgent(lpConn->dwPid);
        }
      }
      //done working
      NktInterlockedExchange(&(lpDispatcher->nLastWorkTick), (LONG)::GetTickCount());
      NktInterlockedExchange(&(lpDispatcher->nIsWorking), 0);
    }
  }
  //----
  lpCallback->TEC_WorkerThreadEnded();
#undef MESSAGES_PER_ROUND
  return;
}
Example #3
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;
}