#include "ProcessorHandler.h"

#include <stdlib.h>
#include <stdio.h>
//#include <Windows.h>

#include "CountdownTimer.h"

#include "YBWCManager.h"
extern YBWCManager* g_pYBWCManagerInstance;

#include "util.h" // kh 02.08.06 ASSERT macro defintion

ProcessorHandler* ProcessorHandler_Construct(ProcessorHandler* pThis, int nId)
{
  pThis->nId                              = nId;
  pThis->nState                           = PROCESSOR_HANDLER_STATE_INITIALIZED;
  pThis->bLoggedOn                        = FALSE;
  pThis->bSyncedNewGame                   = FALSE;
  pThis->bSyncedSetOption                 = FALSE;
  pThis->bSyncedAfterBroadcast            = FALSE;

  pThis->sProcessorName[0]                = '\0';

  pThis->pHeadRequest                     = NULL;
  pThis->pTailRequest                     = NULL;
  pThis->nBufferedRequestCount            = 0;
  pThis->nBufferedRequestCountMax         = 0;

  pThis->pHeadResult                      = NULL;
  pThis->pTailResult                      = NULL;
  pThis->nBufferedResultCount             = 0;
  pThis->nBufferedResultCountMax          = 0;

  pThis->bHashTableBroadcastTarget        = TRUE;
  pThis->bHistoryTableBroadcastTarget     = TRUE;

  pThis->bOnSameNode                      = FALSE;

  pThis->nTransUsed                       = 0;

  return pThis;
}

void ProcessorHandler_Destruct(ProcessorHandler* pThis)
{
  int nResult;

  if(pThis)
  {
    nResult = ProcessorHandler_WaitForAllSendsCompleted(pThis);

    free(pThis);
  }
}

Request* ProcessorHandler_CreateRequest(ProcessorHandler* pThis)
{
  BOOL            bBreak;

  CountdownTimer* pTimeoutTimer;
  CountdownTimer* pCountdownTimer;

  int             nResult;

  if(pThis->nBufferedRequestCount >= g_pYBWCManagerInstance->pFruitConfiguration->nMaxBufferedRequestCount)
  {
    if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_WARNING_PRIO_1)
    {
      YBWCManager_Printf(g_pYBWCManagerInstance, 
                         "WARNING ProcessorHandler <%d> pThis->nBufferedRequestCount (%d) >= MAX_BUFFERED_REQUEST_COUNT (%d)\n", 
                         pThis->nId,
                         pThis->nBufferedRequestCount,
                         g_pYBWCManagerInstance->pFruitConfiguration->nMaxBufferedRequestCount);
    }

    pTimeoutTimer   = CountdownTimer_Construct((CountdownTimer*)malloc(sizeof(CountdownTimer)), CLEANUP_FOR_COMPLETED_SENDS_TIMEOUT);
    pCountdownTimer = CountdownTimer_Construct((CountdownTimer*)malloc(sizeof(CountdownTimer)), CLEANUP_FOR_COMPLETED_SENDS_POLL_RATE);

    bBreak = FALSE;
    while(!bBreak)
    {
      ProcessorHandler_CleanupForCompletedSends(pThis);

      if(pThis->nBufferedRequestCount >= g_pYBWCManagerInstance->pFruitConfiguration->nMaxBufferedRequestCount)
      {

// kh 05.09.06 service messages here to avoid MPI deadlocks (i.e. enable receiving messages)
// this may cause reentrant problems (i.e. nested dispatching/creating of requests/results)
// but this will be handled on a higher abstraction level (e.g. via internal states, message Ids,
// delayed redispatch etc.)
        nResult = YBWCManager_ServiceMessages(g_pYBWCManagerInstance);
        if(nResult == MPI_SUCCESS)
        {
        }
        else
        {
          if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
          {
            YBWCManager_Printf(g_pYBWCManagerInstance, "ERROR ProcessorHandler_CreateRequest(... failed at YBWCManager_ServiceMessages(..., errorcode = %d\n", nResult);
          }
        }

        if((CLEANUP_FOR_COMPLETED_SENDS_TIMEOUT == 0) || CountdownTimer_IsRunning(pTimeoutTimer))
        {

// kh 16.11.06 fastest message handling (a processor should have nothing else to compute anyway)
//        CountdownTimer_WaitAndRestart(pCountdownTimer);

//        Beep(1000, 50);
        }
        else
        {
          bBreak = TRUE;
        }
      } // if(pThis->nBufferedRequestCount >= MAX_BUFFERED_REQUEST_COUNT)
      else
      {
        bBreak = TRUE;
      } // !if(pThis->nBufferedRequestCount >= MAX_BUFFERED_REQUEST_COUNT)
    } // while(!bBreak)

    CountdownTimer_Destruct(pCountdownTimer);
    CountdownTimer_Destruct(pTimeoutTimer);
  } // if(pThis->nBufferedRequestCount >= MAX_BUFFERED_REQUEST_COUNT)

  if(pThis->pHeadRequest == NULL)
  {
    ASSERT(pThis->pTailRequest == NULL)
    pThis->pHeadRequest = Request_Construct((Request*)malloc(sizeof(Request)));
    pThis->pTailRequest = pThis->pHeadRequest;
  }
  else
  {
    ASSERT(pThis->pTailRequest);
    ASSERT(pThis->pTailRequest->pNext == NULL);
    pThis->pTailRequest->pNext = Request_Construct((Request*)malloc(sizeof(Request)));
    pThis->pTailRequest = pThis->pTailRequest->pNext;
  }

  pThis->nBufferedRequestCount++;
  if(pThis->nBufferedRequestCount > pThis->nBufferedRequestCountMax)
  {
    pThis->nBufferedRequestCountMax = pThis->nBufferedRequestCount;
    if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_WARNING_PRIO_1)
    {
      YBWCManager_Printf(g_pYBWCManagerInstance, 
                         "WARNING ProcessorHandler <%d> pThis->nBufferedRequestCountMax = %d\n", 
                         pThis->nId,
                         pThis->nBufferedRequestCountMax);
    }
  }

  pThis->pTailRequest->nDestId = pThis->nId;

  return pThis->pTailRequest;
}

Result* ProcessorHandler_CreateResult(ProcessorHandler* pThis)
{
  BOOL            bBreak;

  CountdownTimer* pTimeoutTimer;
  CountdownTimer* pCountdownTimer;

  int             nResult;

  if(pThis->nBufferedResultCount >= g_pYBWCManagerInstance->pFruitConfiguration->nMaxBufferedResultCount)
  {
    if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_WARNING_PRIO_1)
    {
      YBWCManager_Printf(g_pYBWCManagerInstance, 
                         "WARNING ProcessorHandler <%d> pThis->nBufferedResultCount (%d) >= MAX_BUFFERED_RESULT_COUNT (%d)\n", 
                         pThis->nId,
                         pThis->nBufferedResultCount,
                         g_pYBWCManagerInstance->pFruitConfiguration->nMaxBufferedResultCount);
    }

    pTimeoutTimer   = CountdownTimer_Construct((CountdownTimer*)malloc(sizeof(CountdownTimer)), CLEANUP_FOR_COMPLETED_SENDS_TIMEOUT);
    pCountdownTimer = CountdownTimer_Construct((CountdownTimer*)malloc(sizeof(CountdownTimer)), CLEANUP_FOR_COMPLETED_SENDS_POLL_RATE);

    bBreak = FALSE;
    while(!bBreak)
    {
      ProcessorHandler_CleanupForCompletedSends(pThis);

      if(pThis->nBufferedResultCount >= g_pYBWCManagerInstance->pFruitConfiguration->nMaxBufferedResultCount)
      {

// kh 05.09.06 service messages here to avoid MPI deadlocks (i.e. enable receiving messages)
// this may cause reentrant problems (i.e. nested dispatching/creating of requests/results)
// but this will be handled on a higher abstraction level (e.g. via internal states, message Ids,
// delayed redispatch etc.)
        nResult = YBWCManager_ServiceMessages(g_pYBWCManagerInstance);
        if(nResult == MPI_SUCCESS)
        {
        }
        else
        {
          if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
          {
            YBWCManager_Printf(g_pYBWCManagerInstance, "ERROR ProcessorHandler_CreateResult(... failed at YBWCManager_ServiceMessages(..., errorcode = %d\n", nResult);
          }
        }

        if((CLEANUP_FOR_COMPLETED_SENDS_TIMEOUT == 0) || CountdownTimer_IsRunning(pTimeoutTimer))
        {

// kh 16.11.06 fastest message handling (a processor should have nothing else to compute anyway)
//        CountdownTimer_WaitAndRestart(pCountdownTimer);

//        Beep(1000, 50);
        }
        else
        {
          bBreak = TRUE;
        }
      } // if(pThis->nBufferedResultCount >= MAX_BUFFERED_RESULT_COUNT)
      else
      {
        bBreak = TRUE;
      } // !if(pThis->nBufferedResultCount >= MAX_BUFFERED_RESULT_COUNT)
    } // while(!bBreak)

    CountdownTimer_Destruct(pCountdownTimer);
    CountdownTimer_Destruct(pTimeoutTimer);
  } // if(pThis->nBufferedResultCount >= MAX_BUFFERED_RESULT_COUNT)

  if(pThis->pHeadResult == NULL)
  {
    ASSERT(pThis->pTailResult == NULL)
    pThis->pHeadResult = Result_Construct((Result*)malloc(sizeof(Result)));
    pThis->pTailResult = pThis->pHeadResult;
  }
  else
  {
    ASSERT(pThis->pTailResult);
    ASSERT(pThis->pTailResult->pNext == NULL);
    pThis->pTailResult->pNext = Result_Construct((Result*)malloc(sizeof(Result)));
    pThis->pTailResult = pThis->pTailResult->pNext;
  }

  pThis->nBufferedResultCount++;
  if(pThis->nBufferedResultCount > pThis->nBufferedResultCountMax)
  {
    pThis->nBufferedResultCountMax = pThis->nBufferedResultCount;
    if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_WARNING_PRIO_1)
    {
      YBWCManager_Printf(g_pYBWCManagerInstance, 
                         "WARNING ProcessorHandler <%d> pThis->nBufferedResultCountMax = %d\n", 
                         pThis->nId,
                         pThis->nBufferedResultCountMax);
    }
  }

  pThis->pTailResult->nDestId = pThis->nId;

  return pThis->pTailResult;
}

int ProcessorHandler_CleanupForCompletedSends(ProcessorHandler* pThis)
{
  int       nResult;
  BOOL      bBreak;

  Request*  pMemoRequest;
  Result*   pMemoResult;

  nResult = MPI_SUCCESS;

// kh 02.08.06 simple (ordered by head only access of the queue) delete logic, 
// may be optimized on demand (e.g. iterate completety through the list
// to delete all no more pending results etc.)
  bBreak = FALSE;
  while((pThis->nBufferedRequestCount > 0) && !bBreak)
  {
    if(Request_IsSendPending(pThis->pHeadRequest))
    {
      bBreak = TRUE;

      if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_WARNING_PRIO_2)
      {
        YBWCManager_Printf(g_pYBWCManagerInstance, "WARNING ProcessorHandler <%d> transmission of pHeadRequest is pending\n", pThis->nId);
      }
    }
    else
    {
      pMemoRequest        = pThis->pHeadRequest;
      pThis->pHeadRequest = pThis->pHeadRequest->pNext;
      if(pThis->pHeadRequest == NULL)
      {
        ASSERT(pMemoRequest == pThis->pTailRequest);
        pThis->pTailRequest = NULL;
      }

      Request_Destruct(pMemoRequest);
      pThis->nBufferedRequestCount--;
      ASSERT(pThis->nBufferedRequestCount >= 0);
    }
  }

// kh 02.08.06 simple (ordered by head only access of the queue) delete logic, 
// may be optimized on demand (e.g. iterate completety through the list
// to delete all no more pending results etc.)
  bBreak = FALSE;
  while((pThis->nBufferedResultCount > 0) && !bBreak)
  {
    if(Result_IsSendPending(pThis->pHeadResult))
    {
      bBreak = TRUE;
      if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_WARNING_PRIO_2)
      {
        YBWCManager_Printf(g_pYBWCManagerInstance, "WARNING ProcessorHandler <%d> transmission of pHeadResult is pending\n", pThis->nId);
      }
    }
    else
    {
      pMemoResult        = pThis->pHeadResult;
      pThis->pHeadResult = pThis->pHeadResult->pNext;
      if(pThis->pHeadResult == NULL)
      {
        ASSERT(pMemoResult == pThis->pTailResult);
        pThis->pTailResult = NULL;
      }

      Result_Destruct(pMemoResult);
      pThis->nBufferedResultCount--;
      ASSERT(pThis->nBufferedResultCount >= 0);
    }
  }

  return nResult;
}

int ProcessorHandler_CleanupForCompletedSendsNew(ProcessorHandler* pThis)
{
  int       nResult;
  bool      bBreak;

  Request*  pMemoRequest;
  Result*   pMemoResult;

  Request*  pRequest;
  Request*  pRequestPrev;

  Result*   pResult;
  Result*   pResultPrev;

  int       i;
  int       nRangeStart;
  int       nRangeEnd;
  int       bRangeFirst;

  nResult = MPI_SUCCESS;

// kh 16.11.06 simple iterate completety through the list to delete all no more pending requests
  bBreak        = false;
  i             = 0;
  pRequestPrev  = NULL;
  pRequest      = pThis->pHeadRequest;

  bRangeFirst   = true;

  while(pRequest && !bBreak)
  {
    if(Request_IsSendPending(pRequest))
    {
      if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_INFO_PRIO_999)
      {
        YBWCManager_Printf(g_pYBWCManagerInstance, 
                           "ProcessorHandler <%d> transmission of pRequest at linked list position %d is pending\n", 
                           pThis->nId,
                           i);
      }

      if(bRangeFirst)
      {
        nRangeStart = i;
        bRangeFirst = false;
      }
      nRangeEnd = i;

      pRequestPrev  = pRequest;
      pRequest      = pRequest->pNext;
      i++;
    }
    else
    {
      if(pRequestPrev)
      {
        pRequestPrev->pNext = pRequest->pNext;
      }
      else
      {
        pThis->pHeadRequest = pRequest->pNext;
      }

      if(pRequest == pThis->pTailRequest)
      {
        pThis->pTailRequest = pRequestPrev;
      }

      pMemoRequest  = pRequest;
      pRequest      = pRequest->pNext;
      i++;

      if(bRangeFirst)
      {
      }
      else
      {
        if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_INFO_PRIO_1)
        {
          YBWCManager_Printf(g_pYBWCManagerInstance, 
                             "ProcessorHandler <%d> transmission of pRequest(s) from linked list position %d to %d is pending\n", 
                             pThis->nId,
                             nRangeStart,
                             nRangeEnd);
        }

        bRangeFirst = true;
      }

      Request_Destruct(pMemoRequest);
      pThis->nBufferedRequestCount--;
      ASSERT(pThis->nBufferedRequestCount >= 0);

    }
  }

  if(bRangeFirst)
  {
  }
  else
  {
    if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_INFO_PRIO_1)
    {
      YBWCManager_Printf(g_pYBWCManagerInstance, 
                         "ProcessorHandler <%d> transmission of pRequest(s) from linked list position %d to %d is pending\n", 
                         pThis->nId,
                         nRangeStart,
                         nRangeEnd);
    }

    bRangeFirst = true; // kh 16.11.06 defensive
  }

// kh 16.11.06 simple iterate completety through the list to delete all no more pending results
  bBreak       = false;
  i            = 0;
  pResultPrev  = NULL;
  pResult      = pThis->pHeadResult;

  bRangeFirst   = true;

  while(pResult && !bBreak)
  {
    if(Result_IsSendPending(pResult))
    {
      if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_INFO_PRIO_999)
      {
        YBWCManager_Printf(g_pYBWCManagerInstance, 
                           "ProcessorHandler <%d> transmission of pResult at linked list position %d is pending\n", 
                           pThis->nId,
                           i);
      }

      if(bRangeFirst)
      {
        nRangeStart = i;
        bRangeFirst = false;
      }
      nRangeEnd = i;

      pResultPrev  = pResult;
      pResult      = pResult->pNext;
      i++;
    }
    else
    {
      if(pResultPrev)
      {
        pResultPrev->pNext = pResult->pNext;
      }
      else
      {
        pThis->pHeadResult = pResult->pNext;
      }

      if(pResult == pThis->pTailResult)
      {
        pThis->pTailResult = pResultPrev;
      }

      pMemoResult  = pResult;
      pResult      = pResult->pNext;
      i++;

      if(bRangeFirst)
      {
      }
      else
      {
        if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_INFO_PRIO_1)
        {
          YBWCManager_Printf(g_pYBWCManagerInstance, 
                             "ProcessorHandler <%d> transmission of pResult(s) from linked list position %d to %d is pending\n", 
                             pThis->nId,
                             nRangeStart,
                             nRangeEnd);
        }

        bRangeFirst = true;
      }

      Result_Destruct(pMemoResult);
      pThis->nBufferedResultCount--;
      ASSERT(pThis->nBufferedResultCount >= 0);

    }
  }

  if(bRangeFirst)
  {
  }
  else
  {
    if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_INFO_PRIO_1)
    {
      YBWCManager_Printf(g_pYBWCManagerInstance, 
                         "ProcessorHandler <%d> transmission of pRequest(s) from linked list position %d to %d is pending\n", 
                         pThis->nId,
                         nRangeStart,
                         nRangeEnd);
    }

    bRangeFirst = true; // kh 16.11.06 defensive
  }

// kh 02.08.06 simple (ordered by head only access of the queue) delete logic, 
// may be optimized on demand (e.g. iterate completety through the list
// to delete all no more pending results etc.)

  return nResult;
}

int ProcessorHandler_ForcedWaitForAllSendsCompleted(ProcessorHandler* pThis)
{
  int             nResult;
  int             nResultTmp;

  BOOL            bBreak;

/*
  CountdownTimer* pTimeoutTimer;
  CountdownTimer* pCountdownTimer;
*/
  nResultTmp = MPI_SUCCESS;

/*
  pTimeoutTimer   = CountdownTimer_Construct((CountdownTimer*)malloc(sizeof(CountdownTimer)), ALL_SENDS_COMPLETED_TIMEOUT);
  pCountdownTimer = CountdownTimer_Construct((CountdownTimer*)malloc(sizeof(CountdownTimer)), ALL_SENDS_COMPLETED_POLL_RATE);
*/
  bBreak = FALSE;
  while(    ((pThis->nBufferedRequestCount > 0) || (pThis->nBufferedResultCount > 0))
         && !bBreak)
  {
    nResult = ProcessorHandler_CleanupForCompletedSends(pThis);

    if(nResult == MPI_SUCCESS)
    {
      if((pThis->nBufferedRequestCount > 0) || (pThis->nBufferedResultCount > 0))
      {

// kh 05.09.06 service messages here to avoid MPI deadlocks (i.e. enable receiving messages)
// this may cause reentrant problems (i.e. nested dispatching/creating of requests/results)
// but this will be handled on a higher abstraction level (e.g. via internal states, message Ids,
// delayed redispatch etc.)
        nResult = YBWCManager_ServiceMessages(g_pYBWCManagerInstance);
        if(nResult == MPI_SUCCESS)
        {
        }
        else
        {

// kh 05.09.06 save first error only
          if(nResultTmp == MPI_SUCCESS)
          {
            nResultTmp = nResult;
          }

          if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
          {
            YBWCManager_Printf(g_pYBWCManagerInstance, "ERROR ProcessorHandler_WaitForAllSendsCompleted(... failed at YBWCManager_ServiceMessages(..., errorcode = %d\n", nResult);
          }
        }

/*
        if((ALL_SENDS_COMPLETED_TIMEOUT == 0) || CountdownTimer_IsRunning(pTimeoutTimer))
        {
          CountdownTimer_WaitAndRestart(pCountdownTimer);
        }
        else
        {
          if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_WARNING_PRIO_2)
          {
            YBWCManager_Printf(g_pYBWCManagerInstance, "WARNING WaitForRealEngineResultWaitSendCompletedQueue(... time out\n");
          }
          bBreak = true;
        }
*/
      }
    }
    else
    {

// kh 02.08.06 save first error only
      if(nResultTmp == MPI_SUCCESS)
      {
        nResultTmp = nResult;
      }

      if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
      {
        YBWCManager_Printf(g_pYBWCManagerInstance, "ERROR ProcessorHandler_ForcedWaitForAllSendsCompleted(... failed at ProcessorHandler_CleanupForCompletedSends(..., errorcode = %d\n", nResult);
      }

//    bBreak = TRUE;
    }
  }

/*
  CountdownTimer_Destruct(pCountdownTimer);
  CountdownTimer_Destruct(pTimeoutTimer);
*/

  nResult = nResultTmp;

  return nResult;
}

int ProcessorHandler_WaitForAllSendsCompleted(ProcessorHandler* pThis)
{
  int             nResult;
  int             nResultTmp;

  BOOL            bBreak;
 
  CountdownTimer* pTimeoutTimer;
  CountdownTimer* pCountdownTimer;

  nResultTmp = MPI_SUCCESS;

  pTimeoutTimer   = CountdownTimer_Construct((CountdownTimer*)malloc(sizeof(CountdownTimer)), ALL_SENDS_COMPLETED_TIMEOUT);
  pCountdownTimer = CountdownTimer_Construct((CountdownTimer*)malloc(sizeof(CountdownTimer)), ALL_SENDS_COMPLETED_POLL_RATE);

  bBreak = FALSE;
  while(    ((pThis->nBufferedRequestCount > 0) || (pThis->nBufferedResultCount > 0))
         && !bBreak)
  {
    nResult = ProcessorHandler_CleanupForCompletedSends(pThis);

    if(nResult == MPI_SUCCESS)
    {
      if((pThis->nBufferedRequestCount > 0) || (pThis->nBufferedResultCount > 0))
      {

// kh 05.09.06 service messages here to avoid MPI deadlocks (i.e. enable receiving messages)
// this may cause reentrant problems (i.e. nested dispatching/creating of requests/results)
// but this will be handled on a higher abstraction level (e.g. via internal states, message Ids,
// delayed redispatch etc.)
        nResult = YBWCManager_ServiceMessages(g_pYBWCManagerInstance);
        if(nResult == MPI_SUCCESS)
        {
        }
        else
        {

// kh 05.09.06 save first error only
          if(nResultTmp == MPI_SUCCESS)
          {
            nResultTmp = nResult;
          }

          if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
          {
            YBWCManager_Printf(g_pYBWCManagerInstance, "ERROR ProcessorHandler_WaitForAllSendsCompleted(... failed at YBWCManager_ServiceMessages(..., errorcode = %d\n", nResult);
          }
        }

        if((ALL_SENDS_COMPLETED_TIMEOUT == 0) || CountdownTimer_IsRunning(pTimeoutTimer))
        {
          CountdownTimer_WaitAndRestart(pCountdownTimer);
        }
        else
        {
          if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_WARNING_PRIO_2)
          {
            YBWCManager_Printf(g_pYBWCManagerInstance, "WARNING WaitForRealEngineResultWaitSendCompletedQueue(... time out\n");
          }
          bBreak = true;
        }
      }
    }
    else
    {

// kh 02.08.06 save first error only
      if(nResultTmp == MPI_SUCCESS)
      {
        nResultTmp = nResult;
      }

      if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
      {
        YBWCManager_Printf(g_pYBWCManagerInstance, "ERROR ProcessorHandler_WaitForAllSendsCompleted(... failed at ProcessorHandler_CleanupForCompletedSends(..., errorcode = %d\n", nResult);
      }

//    bBreak = TRUE;
    }
  }

  CountdownTimer_Destruct(pCountdownTimer);
  CountdownTimer_Destruct(pTimeoutTimer);

  nResult = nResultTmp;

  return nResult;
}
