#include "YBWCManager.h"

#include <string.h>
#include <stdarg.h>

#if defined(_WIN32) || defined(_WIN64)

//#include <windows.h>

#else // assume POSIX

  #include <sys/time.h>
#endif

#include "CommPrinter.h"

#include "Request.h"

#include "value.h"
#include "pv.h"
#include "search_full.h"
#include "protocol.h"

// kh 20.02.07 exceptionally allow global access for a better performance (avoid function call to YBWCManager_Instance(...) 
YBWCManager* g_pYBWCManagerInstance = NULL;

static YBWCManager* gM                     = NULL; // kh 21.07.06 debug "alias" only

extern Stack g_Stack;

YBWCManager* YBWCManager_Construct(YBWCManager* pThis)
{
  int i;

  gM                                          = pThis; // kh 21.07.06 debug "alias"

  pThis->bDestructActive                      = FALSE;

  pThis->nState                               = YBWC_MANAGER_STATE_INITIALIZED;
  pThis->bLoggedOn                            = FALSE;

  pThis->nInitResult                          = 0;

  pThis->pFruitConfiguration                  = FruitConfiguration_Construct((FruitConfiguration*)malloc(sizeof(FruitConfiguration)));
  pThis->pCommandLine                         = NULL;
  pThis->pAutoTester                          = AutoTester_Construct((AutoTester*)malloc(sizeof(AutoTester)));

  pThis->nRank                                = -1;
  pThis->nSize                                = -1;

  pThis->bRootMaster                          = FALSE;

  pThis->bStartupOk                           = FALSE;

  pThis->bFatalError                          = FALSE;

  pThis->sProgramDisplayName[0]               = '\0';
  strncat(pThis->sProgramDisplayName, INTERNAL_PROGRAM_NAME, MAX_PROGRAM_DISPLAY_NAME_LENGTH);

  pThis->pStack                               = Stack_Construct(/* (Stack*)malloc(sizeof(Stack)) */);

  pThis->pHashTableTransmitBuffer             = NULL;
  pThis->pHashTableReceiveBuffer              = NULL;

  pThis->bEventActive                         = FALSE;

  for(i = 0; i < MAX_PROCESSORS; i++)
  {
    pThis->processorHandlerPool[i] = NULL;
  }

  pThis->nLogonCount                            = 0;
  pThis->nLogoffCount                           = 0;
  pThis->nShutdownCount                         = 0;

  pThis->nSyncedNewGameCount                    = 0;
  pThis->nSyncedSetOptionCount                  = 0;
  pThis->nSyncedAfterBroadcastCount             = 0;
  
  pThis->bSyncPositionHistoryTableFirst         = TRUE; // kh 02.08.07 defensive
  pThis->bHistoryTableInitialized               = FALSE;

  pThis->nHistoryUpdateCount                    = 0;
  pThis->nHistTotUpdateCount                    = 0;

  for(i = 0; i < HistorySize; i++) 
  {
    pThis->HistoryTableBuffer[i] = 0;
  }

  for(i = 0; i < HistorySize; i++) 
  {
    pThis->HistHitTableBuffer[i] = 0;
    pThis->HistTotTableBuffer[i] = 0;
  }

  pThis->pRequestDispatcher                     = RequestDispatcher_Construct((RequestDispatcher*)malloc(sizeof(RequestDispatcher)));
  pThis->pHeadDelayedRequest                    = NULL;
  pThis->pTailDelayedRequest                    = NULL;
  pThis->nBufferedDelayedRequestCount           = 0;
  pThis->nBufferedDelayedRequestCountMax        = 0;

  pThis->nServicedRequestsInARowMax             = 0;
  pThis->nServicedResultsInARowMax              = 0;

  pThis->nRerunSearchCounter                    = 0;
  pThis->nRerunSearchCounterMax                 = 0;

  pThis->pResultDispatcher                      = ResultDispatcher_Construct((ResultDispatcher*)malloc(sizeof(ResultDispatcher)));

  pThis->bServiceResultsActive                  = FALSE;

  pThis->pCountdownTimerForIdle                 = NULL;

  pThis->pCountdownTimerForRootMasterIdle       = CountdownTimer_Construct((CountdownTimer*)malloc(sizeof(CountdownTimer)), 
                                                                           YBWC_MANAGER_ROOT_MASTER_NON_SEARCHING_POLL_RATE);

  pThis->pCountdownTimerForNonRootMasterIdle    = CountdownTimer_Construct((CountdownTimer*)malloc(sizeof(CountdownTimer)), 
                                                                           YBWC_MANAGER_NON_ROOT_MASTER_NON_SEARCHING_POLL_RATE);

  pThis->pCountdownTimerForCleanupActions       = CountdownTimer_Construct((CountdownTimer*)malloc(sizeof(CountdownTimer)), 
                                                                           YBWC_MANAGER_CLEANUP_ACTIONS_POLL_RATE);

  pThis->pCountdownTimerDebugWaitForSlave       = NULL;

  pThis->pCountdownTimerDebugWaitForWork        = NULL;

  pThis->pCountdownTimerDebugAtWork             = NULL;

  pThis->pCountdownTimerAwaitingResult          = NULL;

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

  pThis->nRemoteTestProcessorId                 = -1;

  pThis->nMasterId                              = -1;

  pThis->nRequestForWorkWaitCounter             = 0;
  pThis->nNoWorkAvailableInARow                 = 0;
  pThis->nNoWorkAvailableInARowMax              = 0;

  pThis->bElectMasterIdFirst                    = TRUE;

  pThis->nSyncPositionId                        = 0;
  pThis->nWorkId                                = 0;

  pThis->nDebugWaitId                           = 0;

  pThis->bEnableWorkDistribution                = TRUE;

  pThis->bSearchingSubproblem                   = FALSE;
  pThis->pWorkAvailableResult                   = NULL;

  pThis->bStoppingActive                        = FALSE;

  pThis->bPostSearchActive                      = FALSE;

  pThis->bStackStopActive                       = FALSE;

  pThis->bRerunSearch                           = FALSE;

  pThis->bRealStopReceived                      = FALSE;
  pThis->nNodesSinceStopReceive                 = 0;
  pThis->nNodesSinceStopReceiveMax              = 0;

  pThis->nNodesSinceSendResult                  = 0;

  pThis->nUniversalDebugVar1                    = 4711;
  pThis->nUniversalDebugVar2                    = 4712;
  pThis->nUniversalDebugFlag1                   = FALSE;

  pThis->nTotalNodes                            = 0;
  pThis->nTotalNodesNonRootMaster               = 0;

  pThis->nTotalNodesRerunOverhead               = 0;

  pThis->nTotalNodesAbortOverhead               = 0;

  for(i = 0; i < MAX_CALL_POSITIONS; i++)
  {
    pThis->CallPositionStatistics[i].nTotalCalls              = 0;
    pThis->CallPositionStatistics[i].nTotalNodes              = 0;
    pThis->CallPositionStatistics[i].nTotalNodesAbortOverhead = 0;
    pThis->CallPositionStatistics[i].nTotalNodesRerunOverhead = 0;
  }

  pThis->bHashTableMaster                       = FALSE;
  pThis->bHistoryTableMaster                    = FALSE;

  pThis->pHistoryTableBroadcastRequestBuffer    = NULL;
  pThis->pHistTotTableBroadcastRequestBuffer    = NULL;
  
  pThis->dTimeUsedLast                          = 0.0;

  pThis->nTotalWorkRequestedCount               = 0;
  pThis->nTotalWorkStartedCount                 = 0;
  pThis->nTotalWorkAbortedCount                 = 0;
  pThis->nTotalWorkFinishedCount                = 0;

  pThis->nTotalWorkAbortSendCount               = 0;

  pThis->nTotalUpdateSearchWindowSendCount      = 0;
  
  pThis->nTotalForcedWindowUpdateRerunCount     = 0;

  pThis->nSharedTranspositionTableAttachType    = SHARED_MEMORY_ATTACH_TYPE_NONE;
  pThis->hMapSharedTranspositionTable           = NULL;
  pThis->pSharedTranspositionTable              = NULL;
  pThis->nSharedTranspositionTableMemoryId      = 0;

  pThis->nSharedHistoryTableAttachType          = SHARED_MEMORY_ATTACH_TYPE_NONE;
  pThis->hMapSharedHistoryTable                 = NULL;
  pThis->pSharedHistoryTable                    = NULL;
  pThis->nSharedHistoryTableMemoryId            = 0;
  pThis->pCriticalSectionHistoryTable           = NULL;

  pThis->bHasAnyTableBroadcastTarget            = FALSE;
  pThis->bPotentialBroadcastTranspositionTable  = FALSE;

  pThis->bPotentialBroadcastHistoryTable        = FALSE;

  pThis->nSlaveNodesReceivedInBetween           = 0;
  pThis->nAllSlaveNodesReceivedInBetween        = 0;
  pThis->nNodesSinceAbort                       = 0;

  pThis->bFruitInit                             = FALSE;

  pThis->nYBWCManager_ProcessSlaveResult        = 0;
  pThis->nYBWCManager_CheckSendWorkToSlave      = 0;

//pThis->nLevel1MoveListTotalCountMax           = 0;

  pThis->nCleanupActionsCounter                 = 0;

  pThis->nTimerActionsCounter01                 = 0;

  pThis->bResizeHashTableActive                 = FALSE;

  pThis->bRestoreBestFromBestLast               = FALSE;

  return pThis;
}

void YBWCManager_Destruct(YBWCManager* pThis)
{
  int nResult;
  int i;

  if(pThis)
  {
    if(pThis->bDestructActive)
    {
      // kh 21.09.06 avoid reentrant problems, e.g. if an assertion fails while already destructing
      // which leads to a fatal error (where YBWCManager_Destruct(... is also called
    } // if(pThis->bDestructActive)
    else
    {
      pThis->bDestructActive = TRUE;

      nResult = YBWCManager_Finalize(pThis);
      if(nResult == MPI_SUCCESS)
      {
      }
      else
      {
        if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
        {
          YBWCManager_Printf(pThis, "ERROR YBWCManager_Destruct(... failed at YBWCManager_Finalize(..., errorcode = %d\n", nResult);
        }
      }

      if(pThis->pCountdownTimerDebugWaitForSlave)
      {
        CountdownTimer_Destruct(pThis->pCountdownTimerDebugWaitForSlave);
      }

      if(pThis->pCountdownTimerDebugWaitForWork)
      {
        CountdownTimer_Destruct(pThis->pCountdownTimerDebugWaitForWork);
      }

      if(pThis->pCountdownTimerDebugAtWork)
      {
        CountdownTimer_Destruct(pThis->pCountdownTimerDebugAtWork);
      }

      if(pThis->pCountdownTimerAwaitingResult)
      {
        CountdownTimer_Destruct(pThis->pCountdownTimerAwaitingResult);
      }

      for(i = 0; i < MAX_PROCESSORS; i++)
      {
        if(pThis->processorHandlerPool[i])
        {
          ProcessorHandler_Destruct(pThis->processorHandlerPool[i]);
          pThis->processorHandlerPool[i] = NULL;
        }
      }

      if(pThis->pStack)
      {
        Stack_Destruct(/* pThis->pStack */);
        pThis->pStack = NULL;
      }

      if(pThis->pHistoryTableBroadcastRequestBuffer)
      {
        Request_Destruct(pThis->pHistoryTableBroadcastRequestBuffer);
      }

      if(pThis->pHistTotTableBroadcastRequestBuffer)
      {
        Request_Destruct(pThis->pHistTotTableBroadcastRequestBuffer);
      }

      if(pThis->pHashTableTransmitBuffer)
      {
        HashTableBuffer_Destruct(pThis->pHashTableTransmitBuffer);
        pThis->pHashTableTransmitBuffer = NULL;
      }
      
      if(pThis->pHashTableReceiveBuffer)
      {
        HashTableBuffer_Destruct(pThis->pHashTableReceiveBuffer);
        pThis->pHashTableReceiveBuffer = NULL;
      }
      
      if(pThis->pCountdownTimerForIdle)
      {
        CountdownTimer_Destruct(pThis->pCountdownTimerForIdle);
        pThis->pCountdownTimerForIdle = NULL;
      }

      if(pThis->pCountdownTimerForRootMasterIdle)
      {
        CountdownTimer_Destruct(pThis->pCountdownTimerForRootMasterIdle);
        pThis->pCountdownTimerForRootMasterIdle = NULL;
      }

      if(pThis->pCountdownTimerForNonRootMasterIdle)
      {
        CountdownTimer_Destruct(pThis->pCountdownTimerForNonRootMasterIdle);
        pThis->pCountdownTimerForNonRootMasterIdle = NULL;
      }

      if(pThis->pCountdownTimerForCleanupActions)
      {
        CountdownTimer_Destruct(pThis->pCountdownTimerForCleanupActions);
        pThis->pCountdownTimerForCleanupActions = NULL;
      }

      if(pThis->pRequestDispatcher)
      {
        RequestDispatcher_Destruct(pThis->pRequestDispatcher);
      }

      if(pThis->pResultDispatcher)
      {
        ResultDispatcher_Destruct(pThis->pResultDispatcher);
      }

      if(pThis->pAutoTester)
      {
        AutoTester_Destruct(pThis->pAutoTester);
        pThis->pAutoTester = NULL;
      }

      if(pThis->pCommandLine)
      {
        CommandLine_Destruct(pThis->pCommandLine);
        pThis->pCommandLine = NULL;
      }

      if(pThis->pFruitConfiguration)
      {
        FruitConfiguration_Destruct(pThis->pFruitConfiguration);
        pThis->pFruitConfiguration = NULL;
      }

      free(pThis); 

      gM                     = NULL; // kh 21.07.06 debug "alias" only
      g_pYBWCManagerInstance = NULL;

// kh 21.09.06 pThis is not any longer accessible
//    pThis->bDestructActive = FALSE;

    } // !if(pThis->bDestructActive)
  } // if(pThis)
}

YBWCManager* YBWCManager_Instance(void)
{
  if(g_pYBWCManagerInstance)
  {
  }
  else
  {
    g_pYBWCManagerInstance = YBWCManager_Construct((YBWCManager*)malloc(sizeof(YBWCManager)));
  }

  return g_pYBWCManagerInstance;
}

BOOL YBWCManager_CheckAllStartedUp(YBWCManager* pThis)
{
  ProcessorHandler* pProcessorHandler;
  int               i;
  BOOL              bBreak;

  i       = 1; // kh 01.08.06 ignore RootMasterId 0
  bBreak  = FALSE;

  while((i < pThis->nSize) && !bBreak)
  {
    pProcessorHandler = pThis->processorHandlerPool[i];
    if(pProcessorHandler)
    {
      if(pProcessorHandler->bLoggedOn)
      {
      }
      else
      {
        bBreak = TRUE;
      }
    }
    else
    {
      bBreak = TRUE;
    }

    i++;
  }

  return(!bBreak);
}

BOOL YBWCManager_CheckAllSyncedNewGame(YBWCManager* pThis)
{
  ProcessorHandler* pProcessorHandler;
  int               i;
  BOOL              bBreak;

  i       = 1; // kh 01.08.06 ignore RootMasterId 0
  bBreak  = FALSE;

  while((i < pThis->nSize) && !bBreak)
  {
    pProcessorHandler = pThis->processorHandlerPool[i];
    if(pProcessorHandler)
    {
      if(pProcessorHandler->bSyncedNewGame)
      {
      }
      else
      {
        bBreak = TRUE;
      }
    }
    else
    {
      bBreak = TRUE;
    }

    i++;
  }

  return(!bBreak);
}

BOOL YBWCManager_CheckAllSyncedSetOption(YBWCManager* pThis)
{
  ProcessorHandler* pProcessorHandler;
  int               i;
  BOOL              bBreak;

  i       = 1; // kh 02.07.08 ignore RootMasterId 0
  bBreak  = FALSE;

  while((i < pThis->nSize) && !bBreak)
  {
    pProcessorHandler = pThis->processorHandlerPool[i];
    if(pProcessorHandler)
    {
      if(pProcessorHandler->bSyncedSetOption)
      {
      }
      else
      {
        bBreak = TRUE;
      }
    }
    else
    {
      bBreak = TRUE;
    }

    i++;
  }

  return(!bBreak);
}

BOOL YBWCManager_CheckAllSyncedAfterBroadcast(YBWCManager* pThis)
{
  ProcessorHandler* pProcessorHandler;
  int               i;
  BOOL              bBreak;

  i       = 0; // kh 07.02.08 do not ignore RootMasterId 0
  bBreak  = FALSE;

  while((i < pThis->nSize) && !bBreak)
  {
    if(i == pThis->nRank)
    {
      // kh 07.02.08 skip
    } // if(i == pThis->nRank)
    else
    {
      pProcessorHandler = pThis->processorHandlerPool[i];
      if(pProcessorHandler)
      {
        if(pProcessorHandler->bSyncedAfterBroadcast)
        {
        }
        else
        {
          bBreak = TRUE;
        }
      }
      else
      {
        bBreak = TRUE;
      }
    } // !if(i == pThis->nRank)

    i++;
  }

  return(!bBreak);
}

int YBWCManager_ServiceRequests(YBWCManager* pThis)
{
  int         nResult;
  BOOL        bBreak;

  int         nFlag;
  MPI_Status  mpiStatus;

  Request*    pRequest;
  int         nRequestCounter;

  nRequestCounter = 0;
  bBreak          = FALSE;
  while(!bBreak)
  {
    nResult = MPIWrapper_Iprobe(MPIWrapper_Instance(),
                                MPI_ANY_SOURCE,
                                YBWC_MANAGER_REQUEST_TAG,
                                MPI_COMM_WORLD,
                                &nFlag,
                                &mpiStatus);

    if(nResult == MPI_SUCCESS) 
    {
      if(nFlag)
      {
        pRequest = Request_Construct((Request*)malloc(sizeof(Request)));

        pRequest->nSourceId = mpiStatus.MPI_SOURCE;

        nResult = MPIWrapper_Recv(MPIWrapper_Instance(),
                                  pRequest->pParameterBuffer,
                                  MAX_REQUEST_PARAMETER_BUFFER_SIZE,
                                  MPI_PACKED,
                                  pRequest->nSourceId,
                                  YBWC_MANAGER_REQUEST_TAG,
                                  MPI_COMM_WORLD,
                                  &mpiStatus);

        if(nResult == MPI_SUCCESS)
        {
          nResult = RequestDispatcher_Dispatch(pThis->pRequestDispatcher, pRequest);
          nRequestCounter++;

          if(nResult == MPI_SUCCESS)
          {
          }
          else
          {
            if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
            {
              YBWCManager_Printf(pThis, "ERROR YBWCManager_ServiceRequests(... failed at RequestDispatcher_Dispatch(..., errorcode = %d\n", nResult);
            }
          }
        }
        else
        {
          if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
          {
            YBWCManager_Printf(pThis, "ERROR YBWCManager_ServiceRequests(... failed at MPIWrapper_Recv(..., errorcode = %d\n", nResult);
          }
        }

        if(pRequest->bDelayedDispatch)
        {
        }
        else
        {
          Request_Destruct(pRequest);
        }
      }
      else
      {
        bBreak = TRUE;
      }
    }
    else
    {
      if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
      {
        YBWCManager_Printf(pThis, "ERROR YBWCManager_ServiceRequests(... failed at MPIWrapper_Iprobe(..., errorcode = %d\n", nResult);
      }
      bBreak = TRUE;
    }
  }

  if(nRequestCounter > 1)
  {
    if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_INFO_PRIO_2)
    {
      YBWCManager_Printf(pThis, "YBWCManager_ServiceRequests(... nRequestCounter = %d \n", nRequestCounter);
    }
  }

  if(nRequestCounter > pThis->nServicedRequestsInARowMax)
  {
    pThis->nServicedRequestsInARowMax = nRequestCounter;
    if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_INFO_PRIO_1)
    {
      YBWCManager_Printf(pThis, 
                         "YBWCManager_ServiceRequests(... nServicedRequestInARowMax = %d \n", 
                         pThis->nServicedRequestsInARowMax);
    }
  }

  nResult = MPI_SUCCESS;

  return nResult;
}

int YBWCManager_ServiceResults(YBWCManager* pThis)
{
  int         nResult;
  BOOL        bBreak;

  int         nFlag;
  MPI_Status  mpiStatus;

  Result*     pResult;
  int         nResultCounter;

  nResult         = MPI_SUCCESS;
  nResultCounter  = 0;
 
  if(pThis->bServiceResultsActive && FALSE) // kh 09.10.06 enable recursive calls
  {

// kh 01.08.06 reentrant behavior is normal
///*
    if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_WARNING_PRIO_1)
    {
      YBWCManager_Printf(pThis, "WARNING Reentrant problem in YBWCManager_ServiceResults(...\n");
    }
//*/

  } // if(pThis->bServiceResultsActive)
  else
  {
    pThis->bServiceResultsActive = TRUE;

    bBreak = FALSE;
    while(!bBreak)
    {
      nResult = MPIWrapper_Iprobe(MPIWrapper_Instance(),
                                  MPI_ANY_SOURCE,
                                  YBWC_MANAGER_RESULT_TAG,
                                  MPI_COMM_WORLD,
                                  &nFlag,
                                  &mpiStatus);

      if(nResult == MPI_SUCCESS) 
      {
        if(nFlag)
        {
          pResult = Result_Construct((Result*)malloc(sizeof(Result)));

//        pThis->pResult->nReceivedTimeStamp = GetTickCount();

          pResult->nSourceId = mpiStatus.MPI_SOURCE;

          nResult = MPIWrapper_Recv(MPIWrapper_Instance(),
                                    pResult->pParameterBuffer,
                                    MAX_RESULT_PARAMETER_BUFFER_SIZE,
                                    MPI_PACKED,
                                    pResult->nSourceId,
                                    YBWC_MANAGER_RESULT_TAG,
                                    MPI_COMM_WORLD,
                                    &mpiStatus);

          if(nResult == MPI_SUCCESS)
          {
            nResult = ResultDispatcher_Dispatch(pThis->pResultDispatcher, pResult);
            nResultCounter++;

            if(nResult == MPI_SUCCESS)
            {
            }
            else
            {
              if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
              {
                YBWCManager_Printf(pThis, "ERROR YBWCManager_ServiceResults(... failed at ResultDispatcher_Dispatch(..., errorcode = %d\n", nResult);
              }
            }
          }
          else
          {
            if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
            {
              YBWCManager_Printf(pThis, "ERROR YBWCManager_ServiceResults(... failed at MPIWrapper_Recv(..., errorcode = %d\n", nResult);
            }
          }

          Result_Destruct(pResult);

        }
        else
        {
          bBreak = TRUE;
        }
      }
      else
      {
        if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
        {
          YBWCManager_Printf(pThis, "ERROR YBWCManager_ServiceResults(... failed at MPIWrapper_Iprobe(..., errorcode = %d\n", nResult);
        }
        bBreak = TRUE;
      }
    }

    pThis->bServiceResultsActive = FALSE;
  } // !if(pThis->bServiceResultsActive)

  if(nResultCounter > 1)
  {
    if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_INFO_PRIO_2)
    {
      YBWCManager_Printf(pThis, "YBWCManager_ServiceResults(... nResultCounter = %d \n", nResultCounter);
    }
  }

  if(nResultCounter > pThis->nServicedResultsInARowMax)
  {
    pThis->nServicedResultsInARowMax = nResultCounter;
    if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_INFO_PRIO_1)
    {
      YBWCManager_Printf(pThis, 
                         "YBWCManager_ServiceResults(... nServicedResultsInARowMax = %d \n", 
                         pThis->nServicedResultsInARowMax);
    }
  }

  return nResult;
}

void YBWCManager_TimerActions01(YBWCManager* pThis)
{

// kh 10.12.07 do not any longer use a real timer (performance)
  pThis->nTimerActionsCounter01++;

  if(pThis->nTimerActionsCounter01 >= pThis->pFruitConfiguration->nTimerActionsInterval01)
  {
    pThis->nTimerActionsCounter01 = 0;

    if(pThis->bRootMaster)
    {
      if(pThis->pFruitConfiguration->bSendKeepAliveChars)
      {

// kh 12.10 regularly send some characters to the gui to keep the ssh protocol alive and 
// solve some flush buffer problems in certain linux environments when plink is used 
// in connection with the chessbase gui      
        send("info keepalive");
      }
    }
  }
}

int YBWCManager_CleanupActions(YBWCManager* pThis)
{
  int               nResult;
  int               nResultTmp;

  int               i;
  BOOL              bBreak;

  ProcessorHandler* pProcessorHandler;

  nResult     = MPI_SUCCESS;
  nResultTmp  = MPI_SUCCESS;

// kh 31.05.07 do not any longer use a real timer (performance)
  pThis->nCleanupActionsCounter++;

  if(pThis->nCleanupActionsCounter >= pThis->pFruitConfiguration->nCleanupActionsInterval)
//if(CountdownTimer_IsRunning(pThis->pCountdownTimerForCleanupActions))
  {
//  YBWCManager_Printf(pThis, ".");
    pThis->nCleanupActionsCounter = 0;

    i       = 0; // kh 01.08.06 do not ignore RootMasterId 0 
    bBreak  = FALSE;

    while((i < pThis->nSize) && !bBreak)
    {
      pProcessorHandler = pThis->processorHandlerPool[i];
      if(pProcessorHandler)
      {

// kh 05.09.06 try once to do cleanup the cleanup for all completed sends
        nResult = ProcessorHandler_CleanupForCompletedSends(pProcessorHandler);

        if(nResult == MPI_SUCCESS)
        {
        }
        else
        {

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

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

//        bBreak = TRUE;

        }
      }

      i++;
    }

//  CountdownTimer_Restart(pThis->pCountdownTimerForCleanupActions);
  }

  nResult = nResultTmp;

  return nResult;
}

int YBWCManager_ServiceMessages(YBWCManager* pThis)
{
  int                       nResult;

  char                      sTmpMoveString[256];

  int                       nTmpHeightOffset;

  StackEntry*               pStackEntryTmp;

  StackEntry*               pStackEntryDebugTmp;

/*
  ParametersFullRoot*       pFullRootPar;
*/
//LocalDataFullRoot*        pFullRootDat;

/*
  ParametersFullSearch*     pFullSearchPar;
*/
//LocalDataFullSearch*      pFullSearchDat;

/*
  ParametersFullNoNull*     pFullNoNullPar;
*/
//LocalDataFullNoNull*      pFullNoNullDat;

/*
  ParametersFullQuiescence* pFullQuiescencePar;
*/
//LocalDataFullQuiescence*  pFullQuiescenceDat;

  if(pThis->nSize <= 1)
  {

// kh 05.05.08 skip message handling (minor optimization for the single processor version)
    nResult = MPI_SUCCESS; 
  }
  else
  {
    if(pThis->bRootMaster)
    {
    } // if(pThis->bRootMaster)
    else
    {
      if(pThis->nNoWorkAvailableInARow > pThis->nNoWorkAvailableInARowMax)
      {
        pThis->nNoWorkAvailableInARowMax = pThis->nNoWorkAvailableInARow;
        if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_INFO_PRIO_1)
        {
          YBWCManager_Printf(pThis, 
                            "YBWCManager_ServiceMessages(... nNoWorkAvailableInARowMax = %d\n", 
                            pThis->nNoWorkAvailableInARowMax);
        }
      }

      if(pThis->pFruitConfiguration->nDebugWaitForWorkRate > 0)
      {
        if(   (pThis->nState == YBWC_MANAGER_STATE_SEARCHING)
            && pThis->bSearchingSubproblem)
        {
        }
        else
        {
          if(pThis->nNoWorkAvailableInARow > 0)
          {
            if(CountdownTimer_IsRunning(pThis->pCountdownTimerDebugWaitForWork))
            {
            }
            else
            {
              if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_FORCE_OUTPUT)
              {
                YBWCManager_Printf(pThis, 
                                  "waiting for work, no work available in a row = %d\n",
                                  pThis->nNoWorkAvailableInARow);
              }
              CountdownTimer_Restart(pThis->pCountdownTimerDebugWaitForWork);
            }
          }
        }
      } // if(pThis->pFruitConfiguration->nDebugWaitForWorkRate > 0)

      if(pThis->pFruitConfiguration->nDebugAtWorkRate > 0)
      {
        if(CountdownTimer_IsRunning(pThis->pCountdownTimerDebugAtWork))
        {
        }
        else
        {
          if(pThis->nState == YBWC_MANAGER_STATE_SEARCHING)
          {
            if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_FORCE_OUTPUT)
            {
              nTmpHeightOffset = -1;
              if(g_pYBWCManagerInstance->pStack->nCount > 0) // kh 17.03.07 check potential access to the actual search level
              {
                pStackEntryTmp = Stack_PeekAt(/* g_pYBWCManagerInstance->pStack, */
                                              g_pYBWCManagerInstance->pStack->nCount - 1);

                switch(pStackEntryTmp->nCallType)
                {
                case CALL_TYPE_UNDEFINED:
                  ASSERT(false);
                  break;

                case CALL_TYPE_FULL_ROOT:
/*
                  pFullRootPar          = &pStackEntryTmp->parameters.fullRootPar;
*/
//                pFullRootDat          = &pStackEntryTmp->localData.fullRootDat;

                  nTmpHeightOffset = pStackEntryTmp->parameters.fullRootPar.height;
                  break;

                case CALL_TYPE_FULL_SEARCH:
/*
                  pFullSearchPar        = &pStackEntryTmp->parameters.fullSearchPar;
*/
//                pFullSearchDat        = &pStackEntryTmp->localData.fullSearchDat;

                  nTmpHeightOffset = pStackEntryTmp->parameters.fullSearchPar.height;
                  break;

                case CALL_TYPE_FULL_NO_NULL:
/*
                  pFullNoNullPar        = &pStackEntryTmp->parameters.fullNoNullPar;
*/
//                pFullNoNullDat        = &pStackEntryTmp->localData.fullNoNullDat;

                  nTmpHeightOffset = pStackEntryTmp->parameters.fullNoNullPar.height;
                  break;

                case CALL_TYPE_FULL_QUIESCENCE:
/*
                  pFullQuiescencePar    = &pStackEntryTmp->parameters.fullQuiescencePar;
*/
//                pFullQuiescenceDat    = &pStackEntryTmp->localData.fullQuiescenceDat;

                  nTmpHeightOffset = pStackEntryTmp->parameters.fullQuiescencePar.height;
                  break;

                default:
                  ASSERT(false);
                  break;
                } // switch(pStackEntryTmp->nCallType)
              } // if(g_pYBWCManagerInstance->pStack->nCount > 0)

              pStackEntryDebugTmp = StackEntry_Construct((StackEntry*)malloc(sizeof(StackEntry)));
              pStackEntryDebugTmp->nReturnPosition = g_pYBWCManagerInstance->pWorkAvailableResult->nReturnPosition;

              move_to_string(pThis->pWorkAvailableResult->nMove, sTmpMoveString, 256);
              YBWCManager_Printf(pThis, 
                                "at work for master %d/%d from position %s StackIndex %d Move %d %s (%d) WorkId " S64_FORMAT " height/depth %d+%d/%d a=%d b=%d nodes " S64_FORMAT " local " S64_FORMAT "\n",
                                pThis->nMasterId,
                                pThis->pWorkAvailableResult->nSourceId,
                                StackEntry_ReturnPositionToString(pStackEntryDebugTmp),
                                pThis->pWorkAvailableResult->nStackIndex,
                                pThis->pWorkAvailableResult->nMoveListIndex + 1,
                                sTmpMoveString,
                                pThis->pWorkAvailableResult->nMove, 
                                pThis->pWorkAvailableResult->nWorkId,
                                nTmpHeightOffset,
                                pThis->pWorkAvailableResult->nHeight,
                                pThis->pWorkAvailableResult->nDepth,
                                pThis->pWorkAvailableResult->nAlpha,
                                pThis->pWorkAvailableResult->nBeta,
                                SearchCurrent->node_nb,
                                SearchCurrent->node_local_nb);

              StackEntry_Destruct(pStackEntryDebugTmp);
            }
            CountdownTimer_Restart(pThis->pCountdownTimerDebugAtWork);
          }
        }
      } // if(pThis->pFruitConfiguration->nDebugAtWorkRate > 0)
    } // !if(pThis->bRootMaster)

    if(pThis->pFruitConfiguration->nDebugAwaitingResultRate > 0)
    {
      if(CountdownTimer_IsRunning(pThis->pCountdownTimerAwaitingResult))
      {
      }
      else
      {
        Stack_DumpAwaitedSlaveResults(/* pThis->pStack */);
        CountdownTimer_Restart(pThis->pCountdownTimerAwaitingResult);
      }
    } // if(pThis->pFruitConfiguration->nDebugAwaitingResultRate > 0)

    YBWCManager_TimerActions01(pThis);

    nResult = YBWCManager_CleanupActions(pThis);

    if(nResult == MPI_SUCCESS)
    {
      nResult = YBWCManager_ServiceRequests(pThis);

      if(nResult == MPI_SUCCESS)
      {
        nResult = YBWCManager_ServiceResults(pThis);

        if(nResult == MPI_SUCCESS)
        {
        }
        else
        {
          if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
          {
            YBWCManager_Printf(pThis, "ERROR YBWCManager_ServiceMessages(... failed at YBWCManager_ServiceResults(..., errorcode = %d\n", nResult);
          }
        }
      }
      else
      {
        if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
        {
          YBWCManager_Printf(pThis, "ERROR YBWCManager_ServiceMessages(... failed at YBWCManager_ServiceRequests(..., errorcode = %d\n", nResult);
        }
      }
    }
    else
    {
      if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
      {
        YBWCManager_Printf(pThis, "ERROR YBWCManager_ServiceMessages(... failed at YBWCManager_CleanupActions(..., errorcode = %d\n", nResult);
      }
    }
  }

  return nResult;
}

BOOL YBWCManager_CheckAllLoggedOff(YBWCManager* pThis)
{
  ProcessorHandler* pProcessorHandler;
  int               i;
  BOOL              bBreak;

  i       = 1; // kh 01.08.06 ignore RootMasterId 0
  bBreak  = FALSE;

  while((i < pThis->nSize) && !bBreak)
  {
    pProcessorHandler = pThis->processorHandlerPool[i];
    if(pProcessorHandler)
    {
      if(pProcessorHandler->nState == PROCESSOR_HANDLER_STATE_LOGGED_OFF)
      {
      }
      else
      {
        bBreak = TRUE;
      }
    }
    else
    {
      bBreak = TRUE;
    }

    i++;
  }

// kh 21.09.06 in case of a fatal error the non root master can probably not correctly log off 
  return(!bBreak || pThis->bFatalError);
}

BOOL YBWCManager_CheckAllShutdown(YBWCManager* pThis)
{
  ProcessorHandler* pProcessorHandler;
  int               i;
  BOOL              bBreak;

  i       = 1; // kh 01.08.06 ignore RootMasterId 0
  bBreak  = FALSE;

  while((i < pThis->nSize) && !bBreak)
  {
    pProcessorHandler = pThis->processorHandlerPool[i];
    if(pProcessorHandler)
    {
      if(pProcessorHandler->nState == PROCESSOR_HANDLER_STATE_SHUTDOWN)
      {
      }
      else
      {
        bBreak = TRUE;
      }
    }
    else
    {
      bBreak = TRUE;
    }

    i++;
  }

// kh 21.09.06 in case of a fatal error the non root master can probably not correctly shutdown
  return(!bBreak || pThis->bFatalError);
}

int YBWCManager_WaitForNonRootMasterStartedUp(YBWCManager* pThis, unsigned int nTimeout)
{
  int               nResult;
  int               i;
  BOOL              bBreak;

  CountdownTimer*   pTimeoutTimer;
  CountdownTimer*   pCountdownTimer;

  ProcessorHandler* pProcessorHandler;
  Request*          pRequest;

  nResult = MPI_SUCCESS;

  i       = 1; // kh 09.08.06 ignore RootMasterId 0
  bBreak  = FALSE;
  while((i < pThis->nSize) && !bBreak)
  {
    pProcessorHandler = pThis->processorHandlerPool[i];
    pRequest          = ProcessorHandler_CreateRequest(pProcessorHandler);
    nResult           = Request_InitRootMasterLogonInvitation(pRequest);

    if(nResult == MPI_SUCCESS)
    {
      nResult = Request_Send(pRequest);

      if(nResult == MPI_SUCCESS)
      {
      }
      else
      {
        if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
        {
          YBWCManager_Printf(pThis, "ERROR YBWCManager_WaitForNonRootMasterStartedUp(... failed at Request_Send(..., errorcode = %d\n", nResult);
        }
        bBreak = TRUE;
      }
    }
    else
    {
      if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
      {
        YBWCManager_Printf(pThis, "ERROR YBWCManager_WaitForNonRootMasterStartedUp(... failed at Request_InitRootMasterLogonInvitation(..., errorcode = %d\n", nResult);
      }
      bBreak = TRUE;
    }

    i++;
  }

// kh 01.08.06 nTimeout == 0 will be handled as infinite (no) timeout
  pTimeoutTimer   = CountdownTimer_Construct((CountdownTimer*)malloc(sizeof(CountdownTimer)), nTimeout);
  pCountdownTimer = CountdownTimer_Construct((CountdownTimer*)malloc(sizeof(CountdownTimer)), YBWC_MANAGER_STARTED_UP_POLL_RATE);

  if(nResult == MPI_SUCCESS)
  {
    bBreak = FALSE;
    while(!bBreak)
    {

// kh 01.08.06 YBWCManager_ServiceResults(... should be sufficient, but in the case
// a processor is sending requests already during the startup phase, internal
// buffers of the mpi environment may be blocking so YBWCManager_ServiceMessages(...
// is used for defensive reasons
      nResult = YBWCManager_ServiceMessages(pThis);

      if(nResult == MPI_SUCCESS)
      {
        if(YBWCManager_CheckAllStartedUp(pThis))
        {
          bBreak            = TRUE;
          pThis->bStartupOk = TRUE;
        }
      }
      else
      {
        if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
        {
          YBWCManager_Printf(pThis, "ERROR YBWCManager_WaitForNonRootMasterStartedUp(... failed at YBWCManager_ServiceMessages(..., errorcode = %d\n", nResult);
        }
        bBreak = TRUE;
      }

      if(!bBreak)
      {
        if((nTimeout == 0) || CountdownTimer_IsRunning(pTimeoutTimer))
        {
          CountdownTimer_WaitAndRestart(pCountdownTimer);
  //      Beep(1000, 50);
        }
        else
        {
          if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_WARNING_PRIO_1)
          {
            YBWCManager_Printf(pThis, "WARNING YBWCManager_WaitForNonRootMasterStartedUp(... time out\n");
          }
          bBreak = TRUE;
        }
      }
    }
  }

  CountdownTimer_Destruct(pCountdownTimer);
  CountdownTimer_Destruct(pTimeoutTimer);

  return nResult;
}

int YBWCManager_SendNonRootMasterMachineInfo(YBWCManager* pThis)
{
  int               nResult;
  int               i;
  BOOL              bBreak;

  ProcessorHandler* pProcessorHandler;
  Request*          pRequest;

  nResult = MPI_SUCCESS;

  i       = 1; // kh 09.08.06 ignore RootMasterId 0
  bBreak  = FALSE;
  while((i < pThis->nSize) && !bBreak)
  {
    pProcessorHandler = pThis->processorHandlerPool[i];
    pRequest          = ProcessorHandler_CreateRequest(pProcessorHandler);
    nResult           = Request_InitRootMasterMachineInfo(pRequest);

    if(nResult == MPI_SUCCESS)
    {
      nResult = Request_Send(pRequest);

      if(nResult == MPI_SUCCESS)
      {
      }
      else
      {
        if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
        {
          YBWCManager_Printf(pThis, "ERROR YBWCManager_WaitForNonRootMasterLoggedOff(... failed at Request_Send(..., errorcode = %d\n", nResult);
        }
        bBreak = TRUE;
      }
    }
    else
    {
      if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
      {
        YBWCManager_Printf(pThis, "ERROR YBWCManager_WaitForNonRootMasterLoggedOff(... failed at Request_InitRootMasterLogonInvitation(..., errorcode = %d\n", nResult);
      }
      bBreak = TRUE;
    }

    i++;
  }

  return nResult;
}

int YBWCManager_WaitForNonRootMasterLoggedOff(YBWCManager* pThis, unsigned int nTimeout)
{
  int               nResult;
  int               i;
  BOOL              bBreak;

  CountdownTimer*   pTimeoutTimer;
  CountdownTimer*   pCountdownTimer;

  ProcessorHandler* pProcessorHandler;
  Request*          pRequest;

  nResult = MPI_SUCCESS;

  i       = 1; // kh 09.08.06 ignore RootMasterId 0
  bBreak  = FALSE;
  while((i < pThis->nSize) && !bBreak)
  {
    pProcessorHandler = pThis->processorHandlerPool[i];
    pRequest          = ProcessorHandler_CreateRequest(pProcessorHandler);
    nResult           = Request_InitRootMasterLogoffInvitation(pRequest);

    if(nResult == MPI_SUCCESS)
    {
      nResult = Request_Send(pRequest);

      if(nResult == MPI_SUCCESS)
      {
      }
      else
      {
        if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
        {
          YBWCManager_Printf(pThis, "ERROR YBWCManager_WaitForNonRootMasterLoggedOff(... failed at Request_Send(..., errorcode = %d\n", nResult);
        }
        bBreak = TRUE;
      }
    }
    else
    {
      if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
      {
        YBWCManager_Printf(pThis, "ERROR YBWCManager_WaitForNonRootMasterLoggedOff(... failed at Request_InitRootMasterLogonInvitation(..., errorcode = %d\n", nResult);
      }
      bBreak = TRUE;
    }

    i++;
  }

// kh 01.08.06 nTimeout == 0 will be handled as infinite (no) timeout
  pTimeoutTimer   = CountdownTimer_Construct((CountdownTimer*)malloc(sizeof(CountdownTimer)), nTimeout);
  pCountdownTimer = CountdownTimer_Construct((CountdownTimer*)malloc(sizeof(CountdownTimer)), YBWC_MANAGER_LOGGED_OFF_POLL_RATE);

  bBreak = FALSE;
  while(!bBreak)
  {
   
// kh 01.08.06 YBWCManager_ServiceResults(... should be sufficient, but in the case
// a processor is sending requests already during the shutdown phase, internal
// buffers of the mpi environment may be blocking so YBWCManager_ServiceMessages(...
// is used for defensive reasons
    nResult = YBWCManager_ServiceMessages(pThis);

    if(nResult == MPI_SUCCESS)
    {
      if(YBWCManager_CheckAllLoggedOff(pThis))
      {
        bBreak = TRUE;
      }
    }
    else
    {
      if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
      {
        YBWCManager_Printf(pThis, "ERROR YBWCManager_WaitForNonRootMasterLoggedOff(... failed at YBWCManager_ServiceMessages(..., errorcode = %d\n", nResult);
      }
      bBreak = TRUE;
    }

    if(!bBreak)
    {
      if((nTimeout == 0) || CountdownTimer_IsRunning(pTimeoutTimer))
      {
        CountdownTimer_WaitAndRestart(pCountdownTimer);
//      Beep(1000, 50);
      }
      else
      {
        if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_WARNING_PRIO_1)
        {
          YBWCManager_Printf(pThis, "WARNING YBWCManager_WaitForNonRootMasterLoggedOff(... time out\n");
        }
        bBreak = TRUE;
      }
    }
  }

  CountdownTimer_Destruct(pCountdownTimer);
  CountdownTimer_Destruct(pTimeoutTimer);

  return nResult;
}

int YBWCManager_WaitForNonRootMasterShutdown(YBWCManager* pThis, unsigned int nTimeout)
{
  int               nResult;
  int               i;
  BOOL              bBreak;

  CountdownTimer*   pTimeoutTimer;
  CountdownTimer*   pCountdownTimer;

  ProcessorHandler* pProcessorHandler;
  Request*          pRequest;

  nResult = MPI_SUCCESS;

  i       = 1; // kh 09.08.06 ignore RootMasterId 0
  bBreak  = FALSE;
  while((i < pThis->nSize) && !bBreak)
  {
    pProcessorHandler = pThis->processorHandlerPool[i];
    pRequest          = ProcessorHandler_CreateRequest(pProcessorHandler);
    nResult           = Request_InitRootMasterShutdown(pRequest);

    if(nResult == MPI_SUCCESS)
    {
      nResult = Request_Send(pRequest);

      if(nResult == MPI_SUCCESS)
      {
      }
      else
      {
        if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
        {
          YBWCManager_Printf(pThis, "ERROR YBWCManager_WaitForNonRootMasterShutdown(... failed at Request_Send(..., errorcode = %d\n", nResult);
        }
        bBreak = TRUE;
      }
    }
    else
    {
      if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
      {
        YBWCManager_Printf(pThis, "ERROR YBWCManager_WaitForNonRootMasterShutdown(... failed at Request_InitRootMasterLogonInvitation(..., errorcode = %d\n", nResult);
      }
      bBreak = TRUE;
    }

    i++;
  }

// kh 01.08.06 nTimeout == 0 will be handled as infinite (no) timeout
  pTimeoutTimer   = CountdownTimer_Construct((CountdownTimer*)malloc(sizeof(CountdownTimer)), nTimeout);
  pCountdownTimer = CountdownTimer_Construct((CountdownTimer*)malloc(sizeof(CountdownTimer)), YBWC_MANAGER_SHUTDOWN_POLL_RATE);

  bBreak = FALSE;
  while(!bBreak)
  {
   
// kh 01.08.06 YBWCManager_ServiceResults(... should be sufficient, but in the case
// a processor is sending requests already during the shutdown phase, internal
// buffers of the mpi environment may be blocking so YBWCManager_ServiceMessages(...
// is used for defensive reasons
    nResult = YBWCManager_ServiceMessages(pThis);

    if(nResult == MPI_SUCCESS)
    {
      if(YBWCManager_CheckAllShutdown(pThis))
      {
        bBreak = TRUE;
      }
    }
    else
    {
      if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
      {
        YBWCManager_Printf(pThis, "ERROR YBWCManager_WaitForNonRootMasterShutdown(... failed at YBWCManager_ServiceMessages(..., errorcode = %d\n", nResult);
      }
      bBreak = TRUE;
    }

    if(!bBreak)
    {
      if((nTimeout == 0) || CountdownTimer_IsRunning(pTimeoutTimer))
      {
        CountdownTimer_WaitAndRestart(pCountdownTimer);
//      Beep(1000, 50);
      }
      else
      {
        if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_WARNING_PRIO_1)
        {
          YBWCManager_Printf(pThis, "WARNING YBWCManager_WaitForNonRootMasterShutdown(... time out\n");
        }
        bBreak = TRUE;
      }
    }
  }

  CountdownTimer_Destruct(pCountdownTimer);
  CountdownTimer_Destruct(pTimeoutTimer);

  return nResult;
}

int YBWCManager_Init(YBWCManager* pThis, int* pargc, char*** pargv)
{
  int               nResult;
  int               i;

  ProcessorHandler* pProcessorHandler;
  int               nProcessornameLength;

  pThis->pargc = pargc;
  pThis->pargv = pargv;

  nResult = MPI_SUCCESS;

// kh 10.08.06 enable bLogToCommonFile, bLogToFile and bLogToStdout to log all potential 
// errors and warnings until FruitConfiguration_ReadConfigurationFile(...
// has been successfully returned
  YBWCManager_LoadLogSettings(pThis, LogSettings_Instance());

  nResult = MPIWrapper_Comm_size(MPIWrapper_Instance(),
                                 MPI_COMM_WORLD,
                                 &pThis->nSize);

  if(nResult == MPI_SUCCESS)
  {
    for(i = 0; i < pThis->nSize; i++)
    {
      pThis->processorHandlerPool[i] = 
        ProcessorHandler_Construct((ProcessorHandler*)malloc(sizeof(ProcessorHandler)), i);
    }

    nResult = MPIWrapper_Comm_rank(MPIWrapper_Instance(),
                                   MPI_COMM_WORLD,
                                   &pThis->nRank);
    if(nResult == MPI_SUCCESS)
    {
      if(pThis->nRank == 0)
      {
        pThis->bRootMaster = TRUE;
      }

      nResult = MPIWrapper_Get_processor_name(MPIWrapper_Instance(), 
                                              pThis->sProcessorName, 
                                              &nProcessornameLength);
      if(nResult == MPI_SUCCESS)
      {
        if(pThis->bRootMaster)
        {

// kh 13.02.08 special suppress of log to stdout once
          YBWCManager_SaveLogSettings(pThis, LogSettings_Instance());

          pThis->pFruitConfiguration->bLogToStdout = FALSE;

// kh 10.08.06 pFruitConfiguration is not yet accessible here
//        if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_INFO_PRIO_1)
          {
            YBWCManager_Printf(pThis, "Root processor name is <%s>\n", pThis->sProcessorName);
          }

          YBWCManager_LoadLogSettings(pThis, LogSettings_Instance());

          pProcessorHandler = pThis->processorHandlerPool[0];

          pProcessorHandler->sProcessorName[0] = '\0';
          strncat(pProcessorHandler->sProcessorName, pThis->sProcessorName, MPI_MAX_PROCESSOR_NAME);
        }

        pThis->pCommandLine = CommandLine_Construct((CommandLine*)malloc(sizeof(CommandLine)), pargc, pargv);

        if(CommandLine_Parse(pThis->pCommandLine))
        {
          if(*pThis->pCommandLine->pargc > 1)
          {
            if(pThis->bRootMaster) // kh 28.02.07 root master only for the moment
            {
              CommandLine_Dump(pThis->pCommandLine);
            }
          }

          if(FruitConfiguration_ReadConfigurationFile(pThis->pFruitConfiguration, CONFIGURATION_FILE_NAME))
          {
            FruitConfiguration_UpdateOptions(pThis->pFruitConfiguration);

            if(pThis->bRootMaster) // kh 28.02.07 root master only for the moment
            {
//            FruitConfiguration_Dump(pThis->pFruitConfiguration);
            }

// kh 01.02.07
//          pThis->pHashTableTransmitBuffer->nChunkSizeForFlush = pThis->pFruitConfiguration->nBroadcastTranspositionTableChunkSize;

            ASSERT((pThis->pHashTableTransmitBuffer == NULL) && (pThis->pHashTableReceiveBuffer == NULL));
            pThis->pHashTableTransmitBuffer = HashTableBuffer_Construct((HashTableBuffer*)malloc(sizeof(HashTableBuffer)),
                                                                        pThis->pFruitConfiguration->nBroadcastTranspositionTableChunkSize);

            pThis->pHashTableReceiveBuffer  = HashTableBuffer_Construct((HashTableBuffer*)malloc(sizeof(HashTableBuffer)),
                                                                        pThis->pFruitConfiguration->nBroadcastTranspositionTableChunkSize);

            pThis->pCountdownTimerDebugWaitForSlave = CountdownTimer_Construct((CountdownTimer*)malloc(sizeof(CountdownTimer)), 
                                                                               pThis->pFruitConfiguration->nDebugWaitForSlaveRate);

            pThis->pCountdownTimerDebugWaitForWork = CountdownTimer_Construct((CountdownTimer*)malloc(sizeof(CountdownTimer)), 
                                                                              pThis->pFruitConfiguration->nDebugWaitForWorkRate);

            pThis->pCountdownTimerDebugAtWork = CountdownTimer_Construct((CountdownTimer*)malloc(sizeof(CountdownTimer)), 
                                                                         pThis->pFruitConfiguration->nDebugAtWorkRate);

            pThis->pCountdownTimerAwaitingResult = CountdownTimer_Construct((CountdownTimer*)malloc(sizeof(CountdownTimer)), 
                                                                            pThis->pFruitConfiguration->nDebugAwaitingResultRate);

            if(pThis->bRootMaster)
            {
              if(AutoTester_CommandLineToTests(pThis->pAutoTester, pThis->pCommandLine))
              {
                if(pThis->pAutoTester->bAutoTest)
                {
                  AutoTester_Dump(pThis->pAutoTester);
                }
              }
              else
              {
                nResult = MPI_ERR_OTHER;

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

              nResult = YBWCManager_WaitForNonRootMasterStartedUp(pThis, YBWC_MANAGER_NON_ROOT_MASTER_STARTED_UP_TIMEOUT);

              if(nResult == MPI_SUCCESS)
              {
                YBWCManager_SetMachineInfo(pThis);

                nResult = YBWCManager_SendNonRootMasterMachineInfo(pThis); //, YBWC_MANAGER_NON_ROOT_MASTER_STARTED_UP_TIMEOUT);

                if(nResult == MPI_SUCCESS)
                {
                }
                else
                {
                  nResult = MPI_ERR_OTHER;

                  if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
                  {
                    YBWCManager_Printf(pThis, "ERROR YBWCManager_Init(... failed at YBWCManager_WaitForNonRootMasterStartedUp(..., errorcode = %d\n", nResult);
                  } 
                }
              }
              else
              {
                nResult = MPI_ERR_OTHER;

                if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
                {
                  YBWCManager_Printf(pThis, "ERROR YBWCManager_Init(... failed at YBWCManager_WaitForNonRootMasterStartedUp(..., errorcode = %d\n", nResult);
                }
              } // !YBWCManager_WaitForNonRootMasterStartedUp(... success

              pThis->bLoggedOn = TRUE; // kh 06.09.06 the root master is implicitly logged on
            } // if(pThis->bRootMaster)

            for(i = 0; i < pThis->nSize; i++)
            {
              pProcessorHandler = pThis->processorHandlerPool[i];
              if(i == pThis->nRank)
              {
                pProcessorHandler->nState = PROCESSOR_HANDLER_STATE_SEE_YBWC_MANAGER_STATE;
              }
              else
              {
                pProcessorHandler->nState = PROCESSOR_HANDLER_STATE_STATE_NOT_USED_YET;
              }
            }
          } // if(FruitConfiguration_ReadConfigurationFile(pThis->pFruitConfiguration, FRUIT_CONFIGURATION_FILE_NAME))
          else
          {
            nResult = MPI_ERR_OTHER;

// kh 10.08.06 pFruitConfiguration is not accessible due to the error
//          if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
            {
              YBWCManager_Printf(pThis, "ERROR YBWCManager_Init(... failed at FruitConfiguration_ReadConfigurationFile(..., errorcode = %d\n", nResult);
            }
          } // !if(FruitConfiguration_ReadConfigurationFile(pThis->pFruitConfiguration, FRUIT_CONFIGURATION_FILE_NAME))
        } // if(CommandLine_Parse(pThis->pCommandLine))
        else
        {
          nResult = MPI_ERR_OTHER;

// kh 10.08.06 pFruitConfiguration is not accessible due to the error
//        if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
          {
            YBWCManager_Printf(pThis, "ERROR YBWCManager_Init(... failed at CommandLine_Parse(..., errorcode = %d\n", nResult);
          }
        } // !if(CommandLine_Parse(pThis->pCommandLine))
      } // MPIWrapper_Get_processor_name(... success
      else
      {
        nResult = MPI_ERR_OTHER;

// kh 10.08.06 pFruitConfiguration is not accessible due to the error
//      if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
        {
          YBWCManager_Printf(pThis, "ERROR YBWCManager_Init(... failed at MPIWrapper_Get_processor_name(..., errorcode = %d\n", nResult);
        }
      } // !MPIWrapper_Get_processor_name(... success
    } // MPIWrapper_Comm_rank(... success
    else
    {

// kh 10.08.06 pFruitConfiguration is not accessible due to the error
//    if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
      {
        YBWCManager_Printf(pThis, "ERROR YBWCManager_Init(... failed at MPIWrapper_Comm_rank(..., errorcode = %d\n", nResult);
      }
    } // !MPIWrapper_Comm_rank(... success 
  } // MPIWrapper_Comm_size(... success
  else
  {

// kh 10.08.06 pFruitConfiguration is not accessible due to the error
//  if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
    {
      YBWCManager_Printf(pThis, "ERROR YBWCManager_Init(... failed at MPIWrapper_Comm_size(..., errorcode = %d\n", nResult);
    }
  } // !// MPIWrapper_Comm_size(... success

  pThis->nInitResult = nResult;

  return nResult;
}

int YBWCManager_Finalize(YBWCManager* pThis)
{
  int         nResult;

  double      dSpeed;

  int         i;

  int         nCallPosition;

  StackEntry* pStackEntryDebugTmp;  

  int         nTotalNodesRerunOverheadPercent;
  int         nTotalNodesAbortOverheadPercent;

  nResult = MPI_SUCCESS;

  if(pThis->nSyncPositionId > 0)
  {
    if(pThis->bRootMaster)
    {
      ASSERT(pThis->nTotalWorkRequestedCount == 0);
      ASSERT(pThis->nTotalWorkStartedCount   == 0);
      ASSERT(pThis->nTotalWorkAbortedCount   == 0);
      ASSERT(pThis->nTotalWorkFinishedCount  == 0);
    }

// kh 15.12 06 output not really necessary for the root master
    if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_FORCE_OUTPUT)
    {
      YBWCManager_Printf(pThis, 
                         "INFO nTotalWorkRequestedCount " S64_FORMAT "\n", 
                         pThis->nTotalWorkRequestedCount);
      YBWCManager_Printf(pThis, 
                         "INFO nTotalWorkStartedCount " S64_FORMAT "\n", 
                         pThis->nTotalWorkStartedCount);
      YBWCManager_Printf(pThis, 
                         "INFO nTotalWorkAbortedCount " S64_FORMAT "\n", 
                         pThis->nTotalWorkAbortedCount);
      YBWCManager_Printf(pThis, 
                         "INFO nTotalWorkFinishedCount " S64_FORMAT "\n", 
                         pThis->nTotalWorkFinishedCount);
    }

    if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_FORCE_OUTPUT)
    {
      YBWCManager_Printf(pThis, 
                         "INFO nTotalWorkAbortSendCount " S64_FORMAT "\n", 
                         pThis->nTotalWorkAbortSendCount);

      YBWCManager_Printf(pThis, 
                         "INFO nTotalUpdateSearchWindowSendCount " S64_FORMAT "\n", 
                         pThis->nTotalUpdateSearchWindowSendCount);

      YBWCManager_Printf(pThis, 
                         "INFO nTotalForcedWindowUpdateRerunCount " S64_FORMAT "\n", 
                         pThis->nTotalForcedWindowUpdateRerunCount);
    }
  }

  if(pThis->bRootMaster)
  {
    if(pThis->bStartupOk) // kh 20.09.06 trigger shutdown actions only if the startup was ok
    {
      nResult = YBWCManager_WaitForNonRootMasterLoggedOff(pThis, YBWC_MANAGER_NON_ROOT_MASTER_LOGGED_OFF_TIMEOUT);
      if(nResult == MPI_SUCCESS)
      {

// kh 14.12.06 force output
        if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_FORCE_OUTPUT)
        {
          dSpeed = (pThis->dTimeUsedLast >= 1.0) ? double(pThis->nTotalNodes) / pThis->dTimeUsedLast : 0.0;

          YBWCManager_Printf(pThis, 
                             "INFO total nodes searched " S64_FORMAT " total nps %.0f\n", 
                             pThis->nTotalNodes,
                             dSpeed);
        }

// kh 13.12.06 force output 
        if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_FORCE_OUTPUT)
        {
          dSpeed = (pThis->dTimeUsedLast >= 1.0) ? double(pThis->nTotalNodesNonRootMaster +
                                                          pThis->nTotalNodes) / pThis->dTimeUsedLast : 0.0;

          YBWCManager_Printf(pThis, 
                             "INFO total time %.0f sum off all total nodes searched " S64_FORMAT " overall total nps %.0f\n", 
                             pThis->dTimeUsedLast * 1000.0,
                             pThis->nTotalNodesNonRootMaster +
                             pThis->nTotalNodes,
                             dSpeed);
        }

// kh 16.02.07 this is the appropriate place of a "synchronized" detach (potential only, in case the root master 
// is not the owner) of shared memory tables (e.g. a non root master owning a shared memory table will not delete
// this table before the shutdown)
        YBWCManager_DetachSharedMemAll(pThis); 

        nResult = YBWCManager_WaitForNonRootMasterShutdown(pThis, YBWC_MANAGER_NON_ROOT_MASTER_SHUTDOWN_TIMEOUT);
        if(nResult == MPI_SUCCESS)
        {
        }
        else
        {
          if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
          {
            YBWCManager_Printf(pThis, "ERROR YBWCManager_Finalize(... failed at YBWCManager_WaitForNonRootMasterShutdown(..., errorcode = %d\n", nResult);
          }
        }
      }
      else
      {
        if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
        {
          YBWCManager_Printf(pThis, "ERROR YBWCManager_Finalize(... failed at YBWCManager_WaitForNonRootMasterLoggedOff(..., errorcode = %d\n", nResult);
        }
      }
    }
    else
    {
      if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
      {
        YBWCManager_Printf(pThis, "ERROR YBWCManager_Finalize(... shutdown skipped because of an error during the startup phase\n");
      }
    }

    pThis->bLoggedOn = FALSE; // kh 06.09.06 defensive, the root master is implicitly logged off here

// kh 16.02.07 disabled (defensive)
//  YBWCManager_DetachSharedMem(pThis); 

  } // if(pThis->bRootMaster)
  else
  {
    if(pThis->nSyncPositionId > 0)
    {

// kh 15.12.06 force output 
      if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_FORCE_OUTPUT)
      {
        YBWCManager_Printf(pThis, 
                           "INFO total nodes searched " S64_FORMAT " \n", 
                           pThis->nTotalNodes);

        YBWCManager_Printf(pThis, 
                           "INFO total nodes overhead caused by window updates " S64_FORMAT " \n", 
                           pThis->nTotalNodesRerunOverhead);

        YBWCManager_Printf(pThis, 
                           "INFO total nodes overhead caused by aborts " S64_FORMAT " \n", 
                           pThis->nTotalNodesAbortOverhead);

        pStackEntryDebugTmp = StackEntry_Construct((StackEntry*)malloc(sizeof(StackEntry)));

        for(i = 0; i < MAX_CALL_POSITIONS; i++)
        {
          nCallPosition = pThis->pStack->CallIndexToPositionMap[i];
          pStackEntryDebugTmp->nReturnPosition = nCallPosition;

          if(pThis->CallPositionStatistics[i].nTotalCalls > 0)
          {

            if(pThis->CallPositionStatistics[i].nTotalNodes > 0)
            {
              nTotalNodesRerunOverheadPercent = 
                (int)((pThis->CallPositionStatistics[i].nTotalNodesRerunOverhead * 100) / pThis->CallPositionStatistics[i].nTotalNodes);

              nTotalNodesAbortOverheadPercent = 
                (int)((pThis->CallPositionStatistics[i].nTotalNodesAbortOverhead * 100) / pThis->CallPositionStatistics[i].nTotalNodes);
            }

            YBWCManager_Printf(pThis, 
                               "    INFO " S64_FORMAT " work items received from a master node at %s nodes " S64_FORMAT " window overhead " S64_FORMAT " %d%% abort overhead " S64_FORMAT " %d%%\n", 
                               pThis->CallPositionStatistics[i].nTotalCalls,
                               StackEntry_ReturnPositionToString(pStackEntryDebugTmp),
                               pThis->CallPositionStatistics[i].nTotalNodes,
                               pThis->CallPositionStatistics[i].nTotalNodesRerunOverhead,
                               nTotalNodesRerunOverheadPercent,
                               pThis->CallPositionStatistics[i].nTotalNodesAbortOverhead,
                               nTotalNodesAbortOverheadPercent);
          }
        }

        StackEntry_Destruct(pStackEntryDebugTmp);
      }
    }

// kh 19.09.06 delayed requests are not possible here (they can not be dispatched)
     ASSERT(pThis->pHeadDelayedRequest == NULL);
  } // !if(pThis->bRootMaster)

/*
  RequestDispatcher_Destruct(pThis->pRequestDispatcher);
  ResultDispatcher_Destruct(pThis->pResultDispatcher);
*/

  YBWCManager_DeleteSharedMemAll(pThis);

  if(pThis->bFruitInit) // kh 26.02.07 used for the non shared memory tables (see also FruitConfiguration_...)
  {
    trans_free(Trans);
    history_free(gpHistory);
  }

  if(pThis->pCriticalSectionHistoryTable)
  {
    CriticalSection_Destruct(pThis->pCriticalSectionHistoryTable);
    pThis->pCriticalSectionHistoryTable = NULL;
  }

  return nResult;
}

char* YBWCManager_TimeStampShortAsString(YBWCManager* pThis)
{

#if defined(_WIN32) || defined(_WIN64)

  SYSTEMTIME systemTime;

  GetLocalTime(&systemTime);

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

  sprintf(pThis->szTimeStamp, 
          "%02d:%02d:%02d.%03d", 
          systemTime.wHour,
          systemTime.wMinute,
          systemTime.wSecond,
          systemTime.wMilliseconds);

#else

  struct  timeval   tv;
  struct  timezone  tz;
  struct  tm*       pNowLocal;

  time_t  now;
  
  gettimeofday(&tv, &tz);

  now       = tv.tv_sec;

  pNowLocal = localtime(&now);

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

  sprintf(pThis->szTimeStamp, 
          "%02d:%02d:%02d.%03d", 
          pNowLocal->tm_hour,
          pNowLocal->tm_min,
          pNowLocal->tm_sec,
          tv.tv_usec / 1000);

#endif

  return pThis->szTimeStamp;
}

char* YBWCManager_TimeStampAsString(YBWCManager* pThis)
{

#if defined(_WIN32) || defined(_WIN64)

  SYSTEMTIME systemTime;

  GetLocalTime(&systemTime);

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

  sprintf(pThis->szTimeStamp, 
          "%02d.%02d.%04d %02d:%02d:%02d.%03d", 
          systemTime.wDay,
          systemTime.wMonth,
          systemTime.wYear,
          systemTime.wHour,
          systemTime.wMinute,
          systemTime.wSecond,
          systemTime.wMilliseconds);

#else

  struct  timeval   tv;
  struct  timezone  tz;
  struct  tm*       pNowLocal;

  time_t  now;
  
  gettimeofday(&tv, &tz);

  now       = tv.tv_sec;

  pNowLocal = localtime(&now);

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

  sprintf(pThis->szTimeStamp, 
          "%02d.%02d.%04d %02d:%02d:%02d.%03d", 
          pNowLocal->tm_mday,
          pNowLocal->tm_mon + 1,
          pNowLocal->tm_year + 1900,
          pNowLocal->tm_hour,
          pNowLocal->tm_min,
          pNowLocal->tm_sec,
          tv.tv_usec / 1000);

#endif

  return pThis->szTimeStamp;
}

void YBWCManager_Printf(YBWCManager* pThis, const char* format, ...)
{
  va_list   arg_list;

  char      sLine       [16384];
  char      sLogLine    [16384];

//ASSERT(format != NULL);

// kh 30.05.07 check potential logging early (performance)
  if(    (pThis->pFruitConfiguration->bLogToCommonFile) 
      || (pThis->pFruitConfiguration->bLogToFile)
      || (pThis->pFruitConfiguration->bLogToStdout))
  {
    va_start(arg_list, format);
    vsprintf(sLine, format, arg_list);
    va_end(arg_list);

    sprintf(sLogLine, 
            "%s %4d:%s", 
            YBWCManager_TimeStampAsString(pThis), 
            pThis->nRank, 
            sLine);

    if(pThis->pFruitConfiguration->bLogToCommonFile)
    {
      CommPrinter_Mefprint(CommPrinter_Instance(), COMM_PRINTER_COMMON_FILE_ID, sLogLine);
    }

    if(pThis->pFruitConfiguration->bLogToFile)
    {
      if(pThis->nRank >= 0)
      {
        CommPrinter_Mefprint(CommPrinter_Instance(), pThis->nRank,                sLogLine);
      }
    }

    if(pThis->pFruitConfiguration->bLogToStdout)
    {

// kh 22.09.06 fprintf(stdout, ... must not be used in combination with the mpi environment
// it was observed that when using fprintf(stdout, ... e.g. two different output lines of two different 
// processors can get "merged" within the same "physical" output line (e.g. in the protocol window of Arena)
// that can cause problems for the gui which may not correctly detect the uci commands from the engine
// e.g. when something like "bestm<some protocol output of a non root master>ove e2e4\n" is received by the gui
// (see also comment from 22.09.06 for void send(... in protocol.cpp)
//    fprintf(stdout, "%s", sLogLine);
      printf("%s", sLogLine);
      fflush(stdout);
    }
  }
}

void YBWCManager_SaveLogSettings(YBWCManager* pThis, LogSettings* pLogSettings)
{
  pLogSettings->nRank             = pThis->nRank;
  pLogSettings->bLogToCommonFile  = pThis->pFruitConfiguration->bLogToCommonFile;
  pLogSettings->bLogToFile        = pThis->pFruitConfiguration->bLogToFile;
  pLogSettings->bLogToStdout      = pThis->pFruitConfiguration->bLogToStdout;
}

void YBWCManager_LoadLogSettings(YBWCManager* pThis, LogSettings* pLogSettings)
{
  pThis->nRank                                  = pLogSettings->nRank;
  pThis->pFruitConfiguration->bLogToCommonFile  = pLogSettings->bLogToCommonFile;
  pThis->pFruitConfiguration->bLogToFile        = pLogSettings->bLogToFile;
  pThis->pFruitConfiguration->bLogToStdout      = pLogSettings->bLogToStdout;
}

BOOL YBWCManager_NextRequestForWorkSendAlreadyAllowed(YBWCManager* pThis)
{
  BOOL    bResult;

  sint64  nThreshold;
  sint64  nRepeatBlockFactor;
  sint64  nExponentialWaitCount;

  bResult = FALSE;

  nRepeatBlockFactor = pThis->pFruitConfiguration->nRequestForWorkRepeatBlockFactor;
  if(nRepeatBlockFactor < 1) // kh 01.02.07 defensive
  {
    nRepeatBlockFactor = 1;
  }

  nExponentialWaitCount = pThis->nNoWorkAvailableInARow / nRepeatBlockFactor;

// kh 06.09.06 2**48 should be sufficient and there is a limit anyway by REQUEST_FOR_WORK_WAIT_COUNTER_LIMIT 
  if(nExponentialWaitCount > 48) 
  {
    nExponentialWaitCount = 48;
  }

  nThreshold = 0;
  if(nExponentialWaitCount > 0)
  {

// kh 13.10.06 acceptable value (100) tuned for a 3GHz P4, release build (with up to 8 non root master tested)
// this value (100) could also be used as the YBWC_MANAGER_REQUEST_FOR_WORK_WAIT_COUNTER_LIMIT, 
// because even that small value seems not to lead to overheads (at the moment)
    nThreshold = pThis->pFruitConfiguration->nRequestForWorkWaitCounterToDouble << (nExponentialWaitCount - 1);
  }

  if(nThreshold > pThis->pFruitConfiguration->nRequestForWorkWaitCounterLimit)
  {
    nThreshold = pThis->pFruitConfiguration->nRequestForWorkWaitCounterLimit;
  }

  if(pThis->nRequestForWorkWaitCounter >= nThreshold)
  {
    bResult                           = TRUE;
    pThis->nRequestForWorkWaitCounter = 0;
  }
  else
  {
    pThis->nRequestForWorkWaitCounter++;
  }

  return bResult;
}

static int g_nLast = 0;
int YBWCManager_ElectMasterId(YBWCManager* pThis)
{
  int     nResult;
  double  dRandom;

  if(pThis->bElectMasterIdFirst)
  {
    pThis->bElectMasterIdFirst = FALSE;
    srand(4711);
  }
  
  if(pThis->pFruitConfiguration->bOnlyDistributeWorkOfRootMaster)
  {
    nResult = 0; // kh 18.02.08 force election of the root master
  }
  else
  {
    dRandom = (double)rand() / ((double)(RAND_MAX) + (double)(1.0)); // kh 06.09.06 range: 0.0 .. 0.99999...

    nResult = (int)(dRandom * pThis->nSize); // kh 06.09.06 range: 0 .. (nSize - 1)
  }

  if(nResult == pThis->nRank)
  {
    ASSERT(pThis->nRank > 0);
    nResult--; 
  }

/*
// kh 09.06.08 $$$$$$ start temp only
  g_nLast++;
  if(g_nLast >= pThis->nSize)
  {
    g_nLast = 0;
  }
  if(g_nLast == pThis->nRank)
  {
    g_nLast++;
    if(g_nLast >= pThis->nSize)
    {
      g_nLast = 0;
    }
  }
  nResult = g_nLast;
*/
// kh 09.06.08 $$$$$$ end temp only


  ASSERT(nResult >= 0);
  ASSERT(nResult <  pThis->nSize);

  return nResult;
}

int YBWCManager_CheckSendRequestForWork(YBWCManager* pThis)
{
  int               nResult;

  ProcessorHandler* pProcessorHandler;
  Request*          pRequest;

  int               nMasterId;

  int               nSyncPositionIdMemo;

  nResult = MPI_SUCCESS;

// kh 20.09.06 this condition is double-checked (see below, immediately before the real send)
  if(    pThis->bLoggedOn                                      // kh 19.09.06 defensive
      && (pThis->nState == YBWC_MANAGER_STATE_SUPPORT_SEARCH))
  {
    if(YBWCManager_NextRequestForWorkSendAlreadyAllowed(pThis))
    {
      nMasterId         = YBWCManager_ElectMasterId(pThis);

      pProcessorHandler = pThis->processorHandlerPool[nMasterId];

// kh 12.09.06 the state may potentially change while creating 
// a new request if the pending request buffer is full, because messages are serviced then
      pRequest          = ProcessorHandler_CreateRequest(pProcessorHandler); 

      nResult           = Request_InitSlaveTryToGetWork(pRequest, pThis->nSyncPositionId);

      if(nResult == MPI_SUCCESS)
      {
// kh 06.09.06 to avoid reentrant problems, if the state has changed while creating the new request above
        if(    pThis->bLoggedOn                                      // kh 19.09.06 defensive
            && (pThis->nState          == YBWC_MANAGER_STATE_SUPPORT_SEARCH))
        {
          if(pThis->nSyncPositionId == pRequest->nSyncPositionId) // kh 27.09.06 double-check add-on
          {
            nSyncPositionIdMemo = pRequest->nSyncPositionId;

// kh 27.02.07 do this in advance now, because messages are potentially serviced in Request_Send(...
// and the new work request may be e.g. totally handled there already 
            pThis->nMasterId = nMasterId;
            pThis->nState    = YBWC_MANAGER_STATE_REQUEST_FOR_WORK_SEND;
            pThis->nTotalWorkRequestedCount++;

            nResult = Request_Send(pRequest);
            if(nResult == MPI_SUCCESS)
            {
              if(pThis->nSyncPositionId == nSyncPositionIdMemo) // kh 27.02.07 triple-check add-on for debug purposes
              {
              }
              else
              {
                if(pThis->nState == YBWC_MANAGER_STATE_REQUEST_FOR_WORK_SEND)
                {
                  if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
                  {
                    YBWCManager_Printf(pThis, 
                                       "ERROR YBWCManager_CheckSendRequestForWork(... unexpected (1) nSyncPositionId change: expected = %d, actual = %d\n", 
                                       nSyncPositionIdMemo,
                                       pThis->nSyncPositionId);
                  }
                }
                else
                {

// kh 23.04.07 messages are potentially serviced in Request_Send(... ) (see above)
// and the new work request may be e.g. totally handled there already 
// especially the following may happen: the request for work is send and while waiting for the completion of the send
// a RESULT_TYPE_MASTER_NO_WORK_AVAILABLE result is immediately received and dispatched for that request and 
// one (or more) buffered sync position requests are dispatched in YBWCManager_DispatchDelayedRequests(... at the end 
// of the no work available result dispatch
                  if(false && pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_FORCE_OUTPUT)
                  {
                    YBWCManager_Printf(pThis, 
                                       "INFO YBWCManager_CheckSendRequestForWork(... nSyncPositionId change: expected = %d, actual = %d, request was already totally handled immediately after send\n", 
                                       nSyncPositionIdMemo,
                                       pThis->nSyncPositionId);
                  }

                }
              }
            } // if(nResult == MPI_SUCCESS)
            else
            {
              if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
              {
                YBWCManager_Printf(pThis, "ERROR YBWCManager_CheckSendRequestForWork(... failed at Request_Send(..., errorcode = %d\n", nResult);
              }
            } // !if(nResult == MPI_SUCCESS)
          } // if(pThis->nSyncPositionId == pRequest->nSyncPositionId)
          else
          {
            pRequest->bSendSuppressed = TRUE;
            if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
            {
              YBWCManager_Printf(pThis, 
                                 "ERROR YBWCManager_CheckSendRequestForWork(... unexpected (2) nSyncPositionId change: expected = %d, actual = %d\n", 
                                 pRequest->nSyncPositionId,
                                 pThis->nSyncPositionId);
            }
          } // !if(pThis->nSyncPositionId == pRequest->nSyncPositionId)
        } // if(    pThis->bLoggedOn...
        else
        {
          pRequest->bSendSuppressed = TRUE;
          if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
          {
            YBWCManager_Printf(pThis, "ERROR YBWCManager_CheckSendRequestForWork(... unexpected state change: nState = %d\n", pThis->nState);
          }
        }  // !if(    pThis->bLoggedOn...
      } // if(nResult == MPI_SUCCESS)
      else
      {
        if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
        {
          YBWCManager_Printf(pThis, "ERROR YBWCManager_CheckSendRequestForWork(... failed at Request_InitSlaveTryToGetWork(..., errorcode = %d\n", nResult);
        }
      } // !if(nResult == MPI_SUCCESS)
    } // if(YBWCManager_NextRequestForWorkSendAlreadyAllowed(pThis))
  } // if(    pThis->bLoggedOn...

  return nResult;
}

int YBWCManager_CheckSendWorkToSlave(YBWCManager* pThis, int nSlaveId, int nSlaveSyncPositionId)
{
  int               nResult;
  BOOL              bMasterHasSendWork;

  ProcessorHandler* pProcessorHandler;
  Result*           pResult;

  pThis->nYBWCManager_CheckSendWorkToSlave++;

  if(pThis->nYBWCManager_CheckSendWorkToSlave > 1)
  {
    if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_INFO_PRIO_1)
    {
      YBWCManager_Printf(pThis, 
                         "YBWCManager_CheckSendWorkToSlave(... potential reentrant problem, recursion level = %d\n", 
                         pThis->nYBWCManager_CheckSendWorkToSlave);
    }
  }

  nResult             = MPI_SUCCESS;

  bMasterHasSendWork  = FALSE;

  if(pThis->bRootMaster || !pThis->pFruitConfiguration->bOnlyDistributeWorkOfRootMaster)
  {
    if(pThis->nState == YBWC_MANAGER_STATE_SEARCHING)
    {
      if(pThis->nSyncPositionId == nSlaveSyncPositionId)
      {
        if(pThis->bStoppingActive) 
        {
          if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_INFO_PRIO_1)
          {
            YBWCManager_Printf(pThis, "INFO YBWCManager_CheckSendWorkToSlave(... pThis->bStoppingActive is true (master is stopping just now)\n");
          }
        } // if(pThis->bStoppingActive) 
        else
        {
          if(pThis->bStackStopActive) 
          {
            if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_INFO_PRIO_1)
            {
              YBWCManager_Printf(pThis, "INFO YBWCManager_CheckSendWorkToSlave(... pThis->bStackStopgActive is true (master has stopped just now)\n");
            }
          } // if(pThis->bStackStopActive) 
          else
          {
            if(pThis->bEnableWorkDistribution)
            {
              if(pThis->bPostSearchActive)
              {
                if(false && pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_FORCE_OUTPUT)
                {
                  YBWCManager_Printf(pThis, "INFO YBWCManager_CheckSendWorkToSlave(... pThis->bPostSearchActive is true (master has finished his search just now)\n");
                }
              }
              else
              {
                if(pThis->pStack->nStack_UpdateSearchWindowForEntry == 0)
                {
                  bMasterHasSendWork = Stack_HasSendWorkToSlave(/* pThis->pStack, */ nSlaveId, nSlaveSyncPositionId);
                }
                else
                {
                  if(false && pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_FORCE_OUTPUT)
                  {
                    YBWCManager_Printf(pThis, 
                                       "INFO YBWCManager_CheckSendWorkToSlave(... nStack_UpdateSearchWindowForEntry is active (recursion level = %d)\n",
                                       pThis->pStack->nStack_UpdateSearchWindowForEntry);
                  }
                }
              }
            } // if(pThis->bEnableWorkDistribution)
            else
            {
              if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_WARNING_PRIO_1)
              {
                YBWCManager_Printf(pThis, "WARNING YBWCManager_CheckSendWorkToSlave(... pThis->bEnableWorkDistribution is false (reentrant problem)\n");
              }
            } // !if(pThis->bEnableWorkDistribution)
          } // !if(pThis->bStackStopActive)
        } // !if(pThis->bStoppingActive) 
      } // if(pThis->nSyncPositionId == nSlaveSyncPositionId)
      else
      {
        if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_WARNING_PRIO_1)
        {
          YBWCManager_Printf(pThis, "WARNING YBWCManager_CheckSendWorkToSlave(... master and slave position out of sync\n");
        }
      } // !if(pThis->nSyncPositionId == nSlaveSyncPositionId)
    } // if(pThis->nState == YBWC_MANAGER_STATE_SEARCHING)
  } // if(pThis->bRootMaster || !pThis->pFruitConfiguration->bOnlyDistributeWorkOfRootMaster)

  if(bMasterHasSendWork)
  {
  }
  else
  {

// kh 20.09.06 if the master has not send work to the slave, there is no need to 
// double-check any condition 
// the result send to the ("waiting") slave is: there is no work available

    pProcessorHandler = pThis->processorHandlerPool[nSlaveId];
    pResult           = ProcessorHandler_CreateResult(pProcessorHandler);
    nResult           = Result_InitMasterNoWorkAvailable(pResult, nSlaveSyncPositionId);

    if(nResult == MPI_SUCCESS)
    {
      nResult = Result_Send(pResult);
      if(nResult == MPI_SUCCESS)
      {
      }
      else
      {
        if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
        {
          YBWCManager_Printf(pThis, "ERROR YBWCManager_CheckSendWorkToSlave(... failed at Result_Send(..., errorcode = %d\n", nResult);
        }
      }
    }
    else
    {
      if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
      {
        YBWCManager_Printf(pThis, "ERROR YBWCManager_CheckSendWorkToSlave(... failed at Result_InitMasterNoWorkAvailable(..., errorcode = %d\n", nResult);
      }
    }
  }

  pThis->nYBWCManager_CheckSendWorkToSlave--;

  return nResult;
}

int YBWCManager_ProcessSlaveResult(YBWCManager* pThis, Request* pRequest)
{
  int                       nResult;

  StackEntry*               pStackEntryTmp;
  StackEntry*               pStackEntryAbort;
  StackEntry*               pStackEntryModify;

  int                       i;
  int                       nMaxDepthTmp;

  int                       nFullRootDatMemo_i;
  int                       nFullRootDatMemo_move;
  int                       nFullRootDatMemo_value;
  mv_t                      FullRootDatMemo_newPV[HeightMax];

//int                       nFullSearchDatMemo_i;
  int                       nFullSearchDatMemo_move;
  int                       nFullSearchDatMemo_value;
  mv_t                      FullSearchDatMemo_newPV[HeightMax];

  int                       nUpdateSearchWindowResult;

//int                       nStopResult;

  ProcessorHandler*         pProcessorHandler;

  pThis->nYBWCManager_ProcessSlaveResult++;

  if(pThis->nYBWCManager_ProcessSlaveResult > 1)
  {
    if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_WARNING_PRIO_1)
    {
      YBWCManager_Printf(pThis, 
                         "WARNING YBWCManager_ProcessSlaveResult(... potential reentrant problem, recursion level = %d\n", 
                         pThis->nYBWCManager_ProcessSlaveResult);
    }
  }

  nResult = MPI_SUCCESS;

  ASSERT(pThis->nState == YBWC_MANAGER_STATE_SEARCHING);

  pProcessorHandler = pThis->processorHandlerPool[pRequest->nSourceId];
  pProcessorHandler->nTransUsed = pRequest->nTransUsed;


// kh 12.12.06 "gross" nodes are counted now
// kh 15.12.06 but this will produce still a lowerbound only, because recursive subnodes of a slave stopped
// by a cutoff may not anymore counted (i.e. subnodes from a slave he would receive in his role as a master
// from another slave in case he is not stopped)

// kh 04.04.08 sum up nodes even if not searching at the moment to favor "gross" node counting
// (see also comment from 04.04.08 for search_clear(... in search.cpp)
//SearchCurrent->node_nb                  += pRequest->nNodes;

  pThis->nAllSlaveNodesReceivedInBetween  += pRequest->nNodes; 

  if(pRequest->nStackIndex == 0)
  {
// kh 02.02.07 needed to adjust the search count of a locally searched root moves in between
    pThis->nSlaveNodesReceivedInBetween += pRequest->nNodes; 
  }

// kh 27.02.07 MoveNone was observed during debug if the slave search was aborted before even really started
// problem is solved now (see also fruit_work_available_parse_go(...)
  ASSERT(pRequest->nBestMove != MoveNone); 

  if(pRequest->nSyncPositionId == pThis->nSyncPositionId)
  {
    if(pRequest->nStackIndex < pThis->pStack->nCount) // kh 26.10.06 check potential access for stack level 
    {
      pStackEntryTmp = Stack_PeekAt(/* pThis->pStack, */ pRequest->nStackIndex);

      if(pRequest->nMoveListIndex < pStackEntryTmp->nMoveListTotalCount) // kh 26.10.06 check potential access for move list index
      {
        if(pRequest->nWorkId == pStackEntryTmp->WorkIdList[pRequest->nMoveListIndex]) // kh 26.10.06 check key property of nWorkId
        {
          ASSERT(pStackEntryTmp->SlaveList[pRequest->nMoveListIndex] > 0);
          ASSERT(pStackEntryTmp->SlaveList[pRequest->nMoveListIndex] == pRequest->nSourceId);
          ASSERT(!pStackEntryTmp->CompletedList[pRequest->nMoveListIndex]);
          ASSERT(pStackEntryTmp->MoveList[pRequest->nMoveListIndex] == pRequest->nBestMove);
          ASSERT(pStackEntryTmp->NodesList[pRequest->nMoveListIndex] == 0);
          ASSERT(pStackEntryTmp->EvalList[pRequest->nMoveListIndex] == ValueNone);

          pStackEntryTmp->CompletedList[pRequest->nMoveListIndex] = true;
          pStackEntryTmp->NodesList[pRequest->nMoveListIndex]     = pRequest->nNodes;
          pStackEntryTmp->EvalList[pRequest->nMoveListIndex]      = pRequest->nBestValue;

// kh 12.12.06 "net" nodes are counted here ("gross" nodes (see above) are counted at the moment)
//        SearchCurrent->node_nb += pRequest->nNodes;

// kh 28.02.07 avoid inserting moves at pStackEntryTmp->localData.fullSearchDat.played[pStackEntryTmp->localData.fullSearchDat.played_nb++] if the stack entry has already been
// stopped (by a local or remote cutoff) (stack entry is stopped e.g. at cut_full_search:)
// otherwise the ASSERT(pStackEntryTmp->localData.fullSearchDat.played[pStackEntryTmp->localData.fullSearchDat.played_nb - 1] == pStackEntryTmp->localData.fullSearchDat.best_move)
// may be triggered in fullSearch(... affecting the history_bad(... marking
          if(pStackEntryTmp->bStopped) 
          {

// kh 18.03.07 disable in combination with synchronous wait (see also Stack_StopEntry(...)
/*
            if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_FORCE_OUTPUT)
            {
              YBWCManager_Printf(pThis, "INFO late slave result received for already stopped stack entry\n");
            }
*/
          } // if(pStackEntry->bStopped)
          else
          {
            switch(pStackEntryTmp->nCallType)
            {
            case CALL_TYPE_UNDEFINED:
              ASSERT(false);
              break;

            case CALL_TYPE_FULL_ROOT:
// kh 23.05.08 assertion does not hold any longer for toga, because cutoffs at the root level are possible
//            ASSERT(pStackEntryTmp->bIsAlive);

              ASSERT(pStackEntryTmp->parameters.fullRootPar.height == 0);
              nMaxDepthTmp  = pRequest->nMaxDepth + pStackEntryTmp->parameters.fullRootPar.height;
              if(nMaxDepthTmp > SearchCurrent->max_depth) 
              {
                SearchCurrent->max_depth = nMaxDepthTmp;
              }

// kh 26.10.06 the whole code here is similar to the handling in fullSearch(..., 
// (some assertions are added here)

// kh 27.10.06 for slave results received for the root level here any cut off handling 
// is irrelevant (at the moment)
// so e.g. bIsAlive - up to the actual top stack level - has not to be set to false to abort 
// the actual local search
// a result will only be received for the root master here and fruit will simply search "the best move" 
// at the root level

// kh 26.10.06 a subproblem will not be distributed any further at the root level of the subproblem itself
              ASSERT(!pThis->bSearchingSubproblem);

              post_search_update_root(pRequest->nMoveListIndex); // kh 02.02.07

// kh 26.10.06 save actual values and prepare an easy refactoring as a future expansion
              nFullRootDatMemo_i      = pStackEntryTmp->localData.fullRootDat.i;
              nFullRootDatMemo_move   = pStackEntryTmp->localData.fullRootDat.move;
              nFullRootDatMemo_value  = pStackEntryTmp->localData.fullRootDat.value; // kh 27.10.06 defensive, pStackEntryTmp->localData.fullRootDat.value need not really to be saved

// kh 27.10.06 not necessary if pRequest->PV is directly used for pv_cat(... below
              pv_copy(FullRootDatMemo_newPV, pStackEntryTmp->localData.fullRootDat.new_pv); 

              pStackEntryTmp->localData.fullRootDat.i       = pRequest->nMoveListIndex;
              pStackEntryTmp->localData.fullRootDat.move    = pRequest->nBestMove;
              pStackEntryTmp->localData.fullRootDat.value   = pRequest->nBestValue;    

// kh 27.10.06 not necessary if pRequest->PV is directly used for pv_cat(... below
              ASSERT(pRequest->nPVLength >= 1); 

              pv_copy(pStackEntryTmp->localData.fullRootDat.new_pv, &pRequest->PV[1]); // kh 27.10.06 skip the first move (which is always the same as pRequest->nBestMove)

              if(pStackEntryTmp->localData.fullRootDat.move == LIST_MOVE(pStackEntryTmp->parameters.fullRootPar.list, 0))
              {
                pStackEntryTmp->localData.fullRootDat.bIterationConfirmed = true;
                g_pYBWCManagerInstance->bRestoreBestFromBestLast          = FALSE;
              }

              if(pStackEntryTmp->localData.fullRootDat.value <= pStackEntryTmp->parameters.fullRootPar.alpha) // upper bound
              {
                if(pThis->bSearchingSubproblem)
                {
                  ASSERT(false); // kh 26.10.06 see above
                  pStackEntryTmp->parameters.fullRootPar.list->value[pStackEntryTmp->localData.fullRootDat.i] = pStackEntryTmp->localData.fullRootDat.value;
                }
                else
                {

// kh 11.10.06 fruit original assignment
                  pStackEntryTmp->parameters.fullRootPar.list->value[pStackEntryTmp->localData.fullRootDat.i] = pStackEntryTmp->localData.fullRootDat.old_alpha;
                }
              } 
              else if(pStackEntryTmp->localData.fullRootDat.value >= pStackEntryTmp->parameters.fullRootPar.beta) // lower bound
              {
                if(pThis->bSearchingSubproblem)
                {
                  ASSERT(false); // kh 26.10.06 see above
                  pStackEntryTmp->parameters.fullRootPar.list->value[pStackEntryTmp->localData.fullRootDat.i] = pStackEntryTmp->localData.fullRootDat.value;
                }
                else
                {

// kh 11.10.06 fruit original assignment
                  pStackEntryTmp->parameters.fullRootPar.list->value[pStackEntryTmp->localData.fullRootDat.i] = pStackEntryTmp->parameters.fullRootPar.beta;
                }
              } 
              else // alpha < value < beta => exact value
              {
                if(pThis->bSearchingSubproblem)
                {
                  ASSERT(false); // kh 23.03.07 see above
                }

                pStackEntryTmp->parameters.fullRootPar.list->value[pStackEntryTmp->localData.fullRootDat.i] = pStackEntryTmp->localData.fullRootDat.value;
              }

// kh 11.04.07 Thomas Gaksch
              if(   (    (pStackEntryTmp->localData.fullRootDat.value > pStackEntryTmp->localData.fullRootDat.best_value[SearchCurrent->multipv])
                      && (     (pStackEntryTmp->localData.fullRootDat.best_value[SearchCurrent->multipv] == ValueNone) 
                            || (pStackEntryTmp->localData.fullRootDat.value > pStackEntryTmp->parameters.fullRootPar.alpha)))

// kh 11.10.06 force update of the internal data structures if the only pseudo root move
// of a subproblem was searched
                  || pThis->bSearchingSubproblem)
              {
                ASSERT(!pThis->bSearchingSubproblem); // kh 26.10.06 see above

// kh 11.04.07 Thomas Gaksch
                SearchBest[SearchCurrent->multipv].move = pStackEntryTmp->localData.fullRootDat.move;

// kh 11.04.07 Thomas Gaksch
                SearchBest[SearchCurrent->multipv].value = pStackEntryTmp->localData.fullRootDat.value;

                if(pStackEntryTmp->localData.fullRootDat.value <= pStackEntryTmp->parameters.fullRootPar.alpha) // upper bound
                {

// kh 11.04.07 Thomas Gaksch
                  SearchBest[SearchCurrent->multipv].flags = SearchUpper;

                } 
                else if(pStackEntryTmp->localData.fullRootDat.value >= pStackEntryTmp->parameters.fullRootPar.beta) // lower bound
                {

// kh 11.04.07 Thomas Gaksch
                  SearchBest[SearchCurrent->multipv].flags = SearchLower;

                } 
                else // alpha < value < beta => exact value
                {

// kh 11.04.07 Thomas Gaksch
                  SearchBest[SearchCurrent->multipv].flags = SearchExact;

                }

                ASSERT(pRequest->nDepth == pStackEntryTmp->parameters.fullRootPar.depth); // kh 27.10.06 assertion should hold for the root level


// kh 11.04.07 Thomas Gaksch
                SearchBest[SearchCurrent->multipv].depth = pStackEntryTmp->parameters.fullRootPar.depth;
                pv_cat(SearchBest[SearchCurrent->multipv].pv, pStackEntryTmp->localData.fullRootDat.new_pv, pStackEntryTmp->localData.fullRootDat.move);

                if(SearchBest[SearchCurrent->multipv].value >= SearchBestLast[SearchCurrent->multipv].value)
                {
                  pStackEntryTmp->localData.fullRootDat.bIterationConfirmed = true;
                  g_pYBWCManagerInstance->bRestoreBestFromBestLast          = FALSE;
                }

                if(pStackEntryTmp->localData.fullRootDat.bIterationConfirmed)
                {
                  search_update_best();
                }
                else
                {
                  g_pYBWCManagerInstance->bRestoreBestFromBestLast = TRUE;
                }
              }

// kh 11.04.07 Thomas Gaksch
              if(    (pStackEntryTmp->localData.fullRootDat.value > pStackEntryTmp->localData.fullRootDat.best_value[SearchCurrent->multipv])

// kh 26.10.06 the comment from 11.10.06 below only refers (or is valid respectively) to the 
// same code in fullSearch(... 
// kh 11.10.06 force update of the internal data structures if the only pseudo root move 
// of a subproblem was searched
                  || pThis->bSearchingSubproblem)
              {
                ASSERT(!pThis->bSearchingSubproblem); // kh 26.10.06 see above

// kh 11.04.07 Thomas Gaksch
                pStackEntryTmp->localData.fullRootDat.best_value[SearchCurrent->multipv] = pStackEntryTmp->localData.fullRootDat.value;

                if(pStackEntryTmp->localData.fullRootDat.value > pStackEntryTmp->parameters.fullRootPar.alpha) 
                {
                  if(pStackEntryTmp->parameters.fullRootPar.search_type == SearchNormal) 
                  {
                    pStackEntryTmp->parameters.fullRootPar.alpha = pStackEntryTmp->localData.fullRootDat.value;
                  }

                  if(pStackEntryTmp->localData.fullRootDat.value >= pStackEntryTmp->parameters.fullRootPar.beta) 
                  {

// kh 12.04.07 assertion does not hold any longer for toga
//                  ASSERT(false); // kh 26.10.06 see above

// kh 12.04.07 assertion does not hold any longer for toga
/*
// kh 07.09.06 probably possible only in case of searching for a subproblem (where exactly one single
// move is filtered or searched respectively)
                    ASSERT(pThis->bSearchingSubproblem); 
*/

// kh 12.04.07 cutoff at the root level is possible in toga, reenable the break idea
                    pStackEntryTmp->bSlaveCutoffLevel = true;
                    pStackEntryTmp->bIsAlive          = false; // kh 12.04.07 defensive

// kh 22.04.07 memo nodes for debug puposes, memo start count (negative, defensive)
                    pThis->nNodesSinceAbort                 = -SearchCurrent->node_nb;
                    pThis->nAllSlaveNodesReceivedInBetween  = 0;

// kh 20.10.06 disable fruit original break statement to set the CompletedList for all moves
/*
                    break;
*/
                  } // if(pStackEntryTmp->localData.fullRootDat.value >= pStackEntryTmp->parameters.fullRootPar.beta) 
                  else
                  {
                    if(pThis->pFruitConfiguration->bUpdateSearchWindows)
                    {

// kh 09.11.06 update the search windows for all processors for the stack entry
                      nUpdateSearchWindowResult = Stack_UpdateSearchWindowForEntry(/* pThis->pStack, */
                                                                                   pStackEntryTmp,
                                                                                   pStackEntryTmp->localData.fullRootDat.value,
                                                                                   pStackEntryTmp->parameters.fullRootPar.beta);
                      if(nUpdateSearchWindowResult == MPI_SUCCESS)
                      {
                      }
                      else
                      {
                        if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
                        {
                          YBWCManager_Printf(pThis, "ERROR YBWCManager_ProcessSlaveResult(... failed at Stack_UpdateSearchWindowForEntry(..., errorcode = %d\n", nUpdateSearchWindowResult);
                        }
                      }

                      if(g_pYBWCManagerInstance->pFruitConfiguration->bDirectUpdateSearchWindows)
                      {

// kh 23.05.08 do it also local
                        Stack_UpdateSearchWindow(/* pThis->pStack, */ pStackEntryTmp, pRequest->nStackIndex + 1);
                      }

                    } // if(pThis->pFruitConfiguration->bUpdateSearchWindows)
                  } // !if(pStackEntryTmp->localData.fullRootDat.value >= pStackEntryTmp->parameters.fullRootPar.beta)
                } // if(pStackEntryTmp->localData.fullRootDat.value > pStackEntryTmp->parameters.fullRootPar.alpha) 
              } // if(pStackEntryTmp->localData.fullRootDat.value > pStackEntryTmp->localData.fullRootDat.best_value) 

              if(pStackEntryTmp->bSlaveCutoffLevel)
              {
                for(i = pRequest->nStackIndex; i < pThis->pStack->nCount; i++)
                {
                  pStackEntryAbort = Stack_PeekAt(/* pThis->pStack, */ i);
                  pStackEntryAbort->bIsAlive = false;
                }
              } // if(pStackEntryTmp->bSlaveCutoffLevel)

// kh 26.10.06 restore actual values (see save above)
              pStackEntryTmp->localData.fullRootDat.i       = nFullRootDatMemo_i;
              pStackEntryTmp->localData.fullRootDat.move    = nFullRootDatMemo_move;
              pStackEntryTmp->localData.fullRootDat.value   = nFullRootDatMemo_value;

// kh 27.10.06 not necessary if pRequest->PV is directly used (see save above)
              pv_copy(pStackEntryTmp->localData.fullRootDat.new_pv, FullRootDatMemo_newPV);
              break;

            case CALL_TYPE_FULL_SEARCH:
// kh 30.10.06 skip slave results, if node is already no longer alive
// kh 30.10.06 may be optimized as a future expansion by trying to get some useful (partial) information 
// from these results too  
              if(pStackEntryTmp->bIsAlive)
              {
                nMaxDepthTmp  = pRequest->nMaxDepth + pStackEntryTmp->parameters.fullSearchPar.height;
                if(nMaxDepthTmp > SearchCurrent->max_depth) 
                {
                  SearchCurrent->max_depth = nMaxDepthTmp;
                }

                nFullSearchDatMemo_move   = pStackEntryTmp->localData.fullSearchDat.move;
                nFullSearchDatMemo_value  = pStackEntryTmp->localData.fullSearchDat.value; // kh 30.10.06 defensive, pStackEntryTmp->localData.fullSearchDat.value need not really to be saved

// kh 30.10.06 not necessary if pRequest->PV is directly used for pv_cat(... below
                pv_copy(FullSearchDatMemo_newPV, pStackEntryTmp->localData.fullSearchDat.new_pv); 

                pStackEntryTmp->localData.fullSearchDat.move  = pRequest->nBestMove;
                pStackEntryTmp->localData.fullSearchDat.value = pRequest->nBestValue;    

// kh 17.04.07 assertion does not hold any longer for toga if e.g. futility pruning is enabled
/*
// kh 30.10.06 not necessary if pRequest->PV is directly used for pv_cat(... below
                ASSERT(pRequest->nPVLength >= 1); 
*/

                if(pRequest->nPVLength >= 1)
                {
                  pv_copy(pStackEntryTmp->localData.fullSearchDat.new_pv, &pRequest->PV[1]); // kh 30.10.06 skip the first move (which is always the same as pRequest->nBestMove)
                }
                else
                {
                  pStackEntryTmp->localData.fullSearchDat.new_pv[0] = MoveNone;
                }

                pStackEntryTmp->localData.fullSearchDat.played[pStackEntryTmp->localData.fullSearchDat.played_nb++] = pStackEntryTmp->localData.fullSearchDat.move;

                if(pStackEntryTmp->localData.fullSearchDat.value > pStackEntryTmp->localData.fullSearchDat.best_value) 
                {
                  pStackEntryTmp->localData.fullSearchDat.best_value = pStackEntryTmp->localData.fullSearchDat.value;
                  pv_cat(pStackEntryTmp->parameters.fullSearchPar.ppv, pStackEntryTmp->localData.fullSearchDat.new_pv, pStackEntryTmp->localData.fullSearchDat.move);
                  if(pStackEntryTmp->localData.fullSearchDat.value > pStackEntryTmp->parameters.fullSearchPar.alpha) 
                  {
                    pStackEntryTmp->parameters.fullSearchPar.alpha     = pStackEntryTmp->localData.fullSearchDat.value;
                    pStackEntryTmp->localData.fullSearchDat.best_move = pStackEntryTmp->localData.fullSearchDat.move;

                    if((pStackEntryTmp->localData.fullSearchDat.value >= pStackEntryTmp->parameters.fullSearchPar.beta)) // kh 14.12.06 $cut...
                    {

// kh 11.04.07 Thomas Gaksch
//                    history_success(move, board);

// kh 30.10.06 abort via bIsAlive at the moment 
//                    goto cut_full_search;
                      pStackEntryTmp->bSlaveCutoffLevel = true;
                      pStackEntryTmp->bIsAlive          = false; // kh 10.02.07 defensive

// kh 09.02.07 memo nodes for debug puposes, memo start count (negative, defensive)
                      pThis->nNodesSinceAbort                 = -SearchCurrent->node_nb;
                      pThis->nAllSlaveNodesReceivedInBetween  = 0;

                    } // if(pStackEntryTmp->localData.fullSearchDat.value >= pStackEntryTmp->parameters.fullSearchPar.beta)
                    else
                    {
                      if(pThis->pFruitConfiguration->bUpdateSearchWindows)
                      {

// kh 09.11.06 update the search windows for all processors for the stack entry
                        nUpdateSearchWindowResult = Stack_UpdateSearchWindowForEntry(/* pThis->pStack, */
                                                                                     pStackEntryTmp,
                                                                                     pStackEntryTmp->localData.fullSearchDat.value,
                                                                                     pStackEntryTmp->parameters.fullSearchPar.beta);
                        if(nUpdateSearchWindowResult == MPI_SUCCESS)
                        {
                        }
                        else
                        {
                          if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
                          {
                            YBWCManager_Printf(pThis, "ERROR YBWCManager_ProcessSlaveResult(... failed at Stack_UpdateSearchWindowForEntry(..., errorcode = %d\n", nUpdateSearchWindowResult);
                          }
                        }

                        if(g_pYBWCManagerInstance->pFruitConfiguration->bDirectUpdateSearchWindows)
                        {

// kh 23.05.08 do it also local
                          Stack_UpdateSearchWindow(/* pThis->pStack, */ pStackEntryTmp, pRequest->nStackIndex + 1);
                        }

                      } // if(pThis->pFruitConfiguration->bUpdateSearchWindows)
                    } // !if(pStackEntryTmp->localData.fullSearchDat.value >= pStackEntryTmp->parameters.fullSearchPar.beta)
                  } // if(pStackEntryTmp->localData.fullSearchDat.value > pStackEntryTmp->parameters.fullSearchPar.alpha) 
                } // if(pStackEntryTmp->localData.fullSearchDat.value > pStackEntryTmp->localData.fullSearchDat.best_value)

                if(pStackEntryTmp->bSlaveCutoffLevel)
                {
                  for(i = pRequest->nStackIndex; i < pThis->pStack->nCount; i++)
                  {
                    pStackEntryAbort = Stack_PeekAt(/* pThis->pStack, */ i);
                    pStackEntryAbort->bIsAlive = false;
                  }
                } // if(pStackEntryTmp->bSlaveCutoffLevel)
                else
                {

/*
// kh 22.12.06 update the node_type up to the top stack level for the actual search 
// kh 12.02.07 reverse only on initial change to cut node for the cutoff level
                  if(    (pStackEntryTmp->parameters.fullSearchPar.node_type == NodePV) 
                      || (pStackEntryTmp->parameters.fullSearchPar.node_type == NodeAll))
                  {
                    pStackEntryTmp->parameters.fullSearchPar.node_type = NodeCut;
*/

// kh 19.03.07
                  if(pStackEntryTmp->parameters.fullSearchPar.node_type == NodeCut)
                  {
                    pStackEntryTmp->parameters.fullSearchPar.node_type = NodeAll;

// kh 22.02.07 $$$ experiments may be interesting
                    if(false)
                    {
                      for(i = pRequest->nStackIndex + 1; i < pThis->pStack->nCount; i++)
                      {
                        pStackEntryModify = Stack_PeekAt(/* pThis->pStack, */ i);
                        switch(pStackEntryModify->nCallType)
                        {
                        case CALL_TYPE_UNDEFINED:
                          ASSERT(false);
                          break;

                        case CALL_TYPE_FULL_ROOT:
/*
                          pFullRootPar          = &pThis->parameters.fullRootPar;
//                        pFullRootDat          = &pThis->localData.fullRootDat;
*/
                          break;

                        case CALL_TYPE_FULL_SEARCH:
/*
                          pFullSearchParModify  = &pStackEntryModify->parameters.fullSearchPar;
*/
//                        pFullSearchDatModify  = &pStackEntryModify->localData.fullSearchDat;

                          if(pStackEntryModify->parameters.fullSearchPar.node_type == NodeCut) 
                          {
                            pStackEntryModify->parameters.fullSearchPar.node_type = NodeAll;
                          } 
                          else if(pStackEntryModify->parameters.fullSearchPar.node_type == NodeAll) 
                          {
                            pStackEntryModify->parameters.fullSearchPar.node_type = NodeCut;
                          } 
                          else if(pStackEntryModify->parameters.fullSearchPar.node_type == NodePV) 
                          {

// kh 01.02.07 $$$ as a future expansion the pv nodes may change the state alternating (cut - all - cut etc...)
// only starting with a cut node
//                          pStackEntryModify->parameters.fullSearchPar.node_type = NodeCut;
                          } 
                          break;

                        case CALL_TYPE_FULL_NO_NULL:
                          break;

                        case CALL_TYPE_FULL_QUIESCENCE:
                          break;

                        default:
                          ASSERT(false);
                          break;
                        }
                      } // for(i = pRequest->nStackIndex + 1; i < pThis->pStack->nCount; i++)
                    }
                  } // if(    (pStackEntryTmp->parameters.fullSearchPar.node_type == NodePV)
                  else
                  {

// kh 21.03.07      ASSERT(pStackEntryTmp->parameters.fullSearchPar.node_type != NodeCut);
// kh 19.03.07 
//                  ASSERT(pStackEntryTmp->parameters.fullSearchPar.node_type != NodeAll);
//                  ASSERT(pStackEntryTmp->parameters.fullSearchPar.node_type == NodeCut);

/*
                    if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_FORCE_OUTPUT)
                    {
                      YBWCManager_Printf(pThis, 
                                         "process slave result workid = " S64_FORMAT " node type is cut\n", 
                                         pRequest->nWorkId);
                    }
*/

                  } // !if(    (pStackEntryTmp->parameters.fullSearchPar.node_type == NodePV)...
                } // !if(pStackEntryTmp->bSlaveCutoffLevel)

// kh 30.10.06 restore actual values (see save above)
                pStackEntryTmp->localData.fullSearchDat.move  = nFullSearchDatMemo_move;

// kh 09.02.07 do this only, if the entry is still alive
                pStackEntryTmp->localData.fullSearchDat.value = nFullSearchDatMemo_value;

// kh 30.10.06 not necessary if pRequest->PV is directly used (see save above)
                pv_copy(pStackEntryTmp->localData.fullSearchDat.new_pv, FullSearchDatMemo_newPV);

              } // if(pStackEntryTmp->bIsAlive)
              else
              {
                int nBreakpoint = 4711; // kh 30.10.06 for debug purposes only

// kh 12.02.07 as a future expansion it may be eventually meaningful to process the result regardless
// to extract some useful information
              } // !if(pStackEntryTmp->bIsAlive)

              break;

            case CALL_TYPE_FULL_NO_NULL:
              ASSERT(false);
              break;

            case CALL_TYPE_FULL_QUIESCENCE:
              ASSERT(false);
              break;

            default:
              ASSERT(false);
              break;
            } // switch(pStackEntryTmp->nCallType)
          }
        } // if(pRequest->nWorkId == pStackEntryTmp->WorkIdList[pRequest->nMoveListIndex])
        else
        {
          if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_WARNING_PRIO_2)
          {
            YBWCManager_Printf(pThis, 
                               "WARNING YBWCManager_ProcessSlaveResult(... slave result for nWorkId = " F12INT64d " received, but work id = " F12INT64d " \n",
                               pThis->nWorkId,
                               pStackEntryTmp->WorkIdList[pRequest->nMoveListIndex]);
          }
        } // !if(pRequest->nWorkId == pStackEntryTmp->WorkIdList[pRequest->nMoveListIndex])
      } // if(pRequest->nMoveListIndex < pStackEntryTmp->nMoveListTotalCount)
      else
      {
        if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_WARNING_PRIO_2)
        {
          YBWCManager_Printf(pThis, 
                             "WARNING YBWCManager_ProcessSlaveResult(... slave result for nMoveListIndex = %d received, but max move list index = %d\n",
                             pRequest->nMoveListIndex,
                             pStackEntryTmp->nMoveListTotalCount - 1);
        }
      } // !if(pRequest->nMoveListIndex < pStackEntryTmp->nMoveListTotalCount)

    } // if(pRequest->nStackIndex < pThis->pStack->nCount)
    else
    {
      if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_WARNING_PRIO_2)
      {
        YBWCManager_Printf(pThis, 
                           "WARNING YBWCManager_ProcessSlaveResult(... slave result for nStackIndex = %d received, but top level stack index = %d\n",
                           pRequest->nStackIndex,
                           pThis->pStack->nCount - 1);
      }
    } // !if(pRequest->nStackIndex < pThis->pStack->nCount)
  } // if(pRequest->nSyncPositionId == pThis->nSyncPositionId)
  else
  {
    if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_WARNING_PRIO_2)
    {
      YBWCManager_Printf(pThis, 
                         "WARNING YBWCManager_ProcessSlaveResult(... slave result for nSyncPositionId = %d received, but master nSyncPositionId = %d\n",
                         pRequest->nSyncPositionId,
                         pThis->nSyncPositionId);
    }
  } // !if(pRequest->nSyncPositionId == pThis->nSyncPositionId)

  pThis->nYBWCManager_ProcessSlaveResult--;

  return nResult;
}

int YBWCManager_BufferRequestForDelayedDispatch(YBWCManager* pThis, Request* pRequest)
{
  int               nResult;

  nResult = MPI_SUCCESS;

  ASSERT(!pRequest->bDelayedDispatch);

  if(pThis->pHeadDelayedRequest == NULL)
  {
    ASSERT(pThis->pTailDelayedRequest == NULL)
    pThis->pHeadDelayedRequest = pRequest;
    pThis->pTailDelayedRequest = pThis->pHeadDelayedRequest;
  }
  else
  {
    ASSERT(pThis->pTailDelayedRequest);
    ASSERT(pThis->pTailDelayedRequest->pNext == NULL);
    pThis->pTailDelayedRequest->pNext = pRequest;
    pThis->pTailDelayedRequest = pThis->pTailDelayedRequest->pNext;
  }

  pThis->nBufferedDelayedRequestCount++;
  if(pThis->nBufferedDelayedRequestCount > pThis->nBufferedDelayedRequestCountMax)
  {
    pThis->nBufferedDelayedRequestCountMax = pThis->nBufferedDelayedRequestCount;
    if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_WARNING_PRIO_1)
    {
      YBWCManager_Printf(pThis, 
                         "WARNING YBWCManager_BufferRequestForDelayedDispatch(... nBufferedDelayedRequestCountMax = %d\n", 
                         pThis->nBufferedDelayedRequestCountMax);
    }
  }

  pRequest->bDelayedDispatch = TRUE;

  return nResult;
}

int YBWCManager_DispatchDelayedRequests(YBWCManager* pThis)
{
  int               nResult;

  BOOL              bBreak;
  Request*          pMemoRequest;

  int               nRequestCounter;

  nResult         = MPI_SUCCESS;
  nRequestCounter = 0;

  bBreak          = FALSE;
  while(pThis->pHeadDelayedRequest && !bBreak)
  {
    ASSERT(pThis->pHeadDelayedRequest->bDelayedDispatch);

    if(    (pThis->nState == YBWC_MANAGER_STATE_IDLE)
        || (pThis->nState == YBWC_MANAGER_STATE_SUPPORT_SEARCH))
    {
      nResult = RequestDispatcher_Dispatch(pThis->pRequestDispatcher, pThis->pHeadDelayedRequest);
      nRequestCounter++;

      if(nResult == MPI_SUCCESS)
      {
      }
      else
      {
        if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
        {
          YBWCManager_Printf(pThis, "ERROR YBWCManager_DispatchDelayedRequests(... failed at RequestDispatcher_Dispatch(..., errorcode = %d\n", nResult);
        }
      }

      pMemoRequest                = pThis->pHeadDelayedRequest;
      pThis->pHeadDelayedRequest  = pThis->pHeadDelayedRequest->pNext;
      if(pThis->pHeadDelayedRequest == NULL)
      {
        ASSERT(pMemoRequest == pThis->pTailDelayedRequest);
        pThis->pTailDelayedRequest = NULL;
      }

      Request_Destruct(pMemoRequest);
      pThis->nBufferedDelayedRequestCount--;
      ASSERT(pThis->nBufferedDelayedRequestCount >= 0);
    }
    else
    {
      bBreak = TRUE;
    }
  }

  return nResult;
}

int YBWCManager_SetMachineInfo(YBWCManager* pThis)
{
  int               nResult;
  int               i;
  int               j;

  ProcessorHandler* pProcessorHandler;
  ProcessorHandler* pProcessorHandlerCmp;

  BOOL              bBreak;

  nResult = MPI_SUCCESS;

// kh 13.12.06 set the pProcessorHandler->bHashTableBroadcastTarget properties

// kh 13.12.06 do not ignore RootMasterId 0, but pProcessorHandler->bHashTableBroadcastTarget should be true for the root master
  for(i = 0; i < pThis->nSize; i++)
  {
    pProcessorHandler = pThis->processorHandlerPool[i];

    ASSERT(pProcessorHandler);

    if(pProcessorHandler)
    {
      if(strcmp(pProcessorHandler->sProcessorName, pThis->sProcessorName) == 0)
      {
        // kh 13.12.06 do not send to any processor with the same name
        pProcessorHandler->bHashTableBroadcastTarget = FALSE;

// kh 30.04.08 same name same node
        pProcessorHandler->bOnSameNode = TRUE;
      } // if(strcmp(pProcessorHandler->sProcessorName, pThis->sProcessorName) == 0)
      else
      {

// kh 30.04.08 different names different nodes
        pProcessorHandler->bOnSameNode = FALSE;

        j       = 0; // kh 13.12.06 do not ignore RootMasterId 0, but bHashTableMaster should be true for the root master
        bBreak  = FALSE;

        while((j < i) && !bBreak)
        {
          pProcessorHandlerCmp = pThis->processorHandlerPool[j];
          ASSERT(pProcessorHandlerCmp);
          if(pProcessorHandlerCmp)
          {
            if(strcmp(pProcessorHandlerCmp->sProcessorName, pProcessorHandler->sProcessorName) == 0)
            {
              bBreak = TRUE;
            }
          }

          j++;
        } // while((j < i) && !bBreak)

        pProcessorHandler->bHashTableBroadcastTarget = !bBreak;
        if(pProcessorHandler->bHashTableBroadcastTarget)
        {
          pThis->bHasAnyTableBroadcastTarget = TRUE;
        }
      } // !if(strcmp(pProcessorHandler->sProcessorName, pThis->sProcessorName) == 0)

      if(pProcessorHandler->bHashTableBroadcastTarget)
      {
        if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_INFO_PRIO_3)
        {
          YBWCManager_Printf(pThis, 
                             "INFO rank %d on <%s> has bHashTableBroadcastTarget property\n",
                             i,
                             pProcessorHandler->sProcessorName);
        }
      } // if(pProcessorHandler->bHashTableBroadcastTarget)

// kh 20.02.07 as a future expansion another criterion could be used to determine the history table broadcast target property
      pProcessorHandler->bHistoryTableBroadcastTarget = pProcessorHandler->bHashTableBroadcastTarget;

    } // if(pProcessorHandler)

  } // for(i = 0; i < pThis->nSize; i++)

// kh 13.12.06 set the pThis->bHashTableMaster property

  i       = 0; // kh 13.12.06 do not ignore RootMasterId 0, but bHashTableMaster should be true for the root master
  bBreak  = FALSE;

  while((i < pThis->nRank) && !bBreak)
  {
    ASSERT(pProcessorHandler);

    pProcessorHandler = pThis->processorHandlerPool[i];
    if(pProcessorHandler)
    {
      if(strcmp(pProcessorHandler->sProcessorName, pThis->sProcessorName) == 0)
      {
        bBreak = TRUE;
      }
    }
    else
    {
      bBreak = TRUE;
    }
    i++;
  }

  pThis->bHashTableMaster = !bBreak;

  if(pThis->bHashTableMaster)
  {
    if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_INFO_PRIO_3)
    {
      YBWCManager_Printf(pThis, "INFO bHashTableMaster property\n");
    }
  }

// kh 20.02.07 as a future expansion another criterion could be used to determine the history table master property
  pThis->bHistoryTableMaster = pThis->bHashTableMaster;

  if(pThis->pFruitConfiguration->bBroadcastTranspositionTable)
  {
    if(    (pThis->nSize == 1)                                                  // kh 02.02.07 disable buffering for broadcast in this special/rare case
        || (    pThis->pFruitConfiguration->bUseSharedMemoryTranspositionTable  // kh 02.02.07 disable buffering for broadcast on a one machine (name) environment with 2 or more cores
             && !pThis->bHasAnyTableBroadcastTarget))
    {
      if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_FORCE_OUTPUT)
      {
        YBWCManager_Printf(pThis, "INFO bBroadcastTranspositionTable enabled but not really needed\n");
      }
    }
    else
    {
      pThis->bPotentialBroadcastTranspositionTable = TRUE;

      if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_FORCE_OUTPUT)
      {
        YBWCManager_Printf(pThis, "INFO bBroadcastTranspositionTable enabled and potentially needed\n");
      }
    }
  }
  else
  {
    if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_FORCE_OUTPUT)
    {
      YBWCManager_Printf(pThis, "INFO bBroadcastTranspositionTable disabled\n");
    }
  }

  if(pThis->pFruitConfiguration->bBroadcastHistoryTable)
  {
    if(    (pThis->nSize == 1)                                                  // kh 20.02.07 disable buffering for broadcast in this special/rare case
        || (    pThis->pFruitConfiguration->bUseSharedMemoryHistoryTable        // kh 20.02.07 disable buffering for broadcast on a one machine (name) environment with 2 or more cores
             && !pThis->bHasAnyTableBroadcastTarget))
    {
      if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_FORCE_OUTPUT)
      {
        YBWCManager_Printf(pThis, "INFO bBroadcastHistoryTable enabled but not really needed\n");
      }
    }
    else
    {
      pThis->bPotentialBroadcastHistoryTable = TRUE;

      if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_FORCE_OUTPUT)
      {
        YBWCManager_Printf(pThis, "INFO bBroadcastHistoryTable enabled and potentially needed\n");
      }
    }
  }
  else
  {
    if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_FORCE_OUTPUT)
    {
      YBWCManager_Printf(pThis, "INFO bBroadcastHistoryTable disabled\n");
    }
  }

// kh 13.12.06 do not ignore RootMasterId 0, but bHashTableMaster should be true for the root master
  ASSERT(pThis->bHashTableMaster || !pThis->bRootMaster);

  return nResult;
}

int YBWCManager_AdjustProcessPriority(YBWCManager* pThis)
{
  int               nResult;
  ProcessorHandler* pProcessorHandler;

  nResult = MPI_SUCCESS;

// kh 28.11.07 the ChessBase GUI has a display update problem (PV info etc.) if running on the same 
// physical machine and all cores are used for the parallel search
// it seems to be a good idea anyway to prioritize indirect other processes (e.g. the operating system) that way 
  pProcessorHandler = pThis->processorHandlerPool[0];
  if(pProcessorHandler->bHashTableBroadcastTarget)
  {
    // root master is a broadcast target, this process runs on another node
  } // if(pProcessorHandler->bHashTableBroadcastTarget)
  else
  {
    // root master is not a broadcast target, this process runs on the same node

#if defined(_WIN32) || defined(_WIN64)

    if(pThis->pFruitConfiguration->bAdjustProcessPriority)
    {
  		SetPriorityClass(GetCurrentProcess(), BELOW_NORMAL_PRIORITY_CLASS);
    } // if(g_pYBWCManagerInstance->pFruitConfiguration->bAdjustProcessPriority)
    else
    {
  		SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
    } // !if(g_pYBWCManagerInstance->pFruitConfiguration->bAdjustProcessPriority)

#else // assume POSIX

    // kh 13.02.08 todo 

#endif

	} // !if(pProcessorHandler->bHashTableBroadcastTarget)

  return nResult;
}

int YBWCManager_HookPosition(YBWCManager* pThis, char* szPosition)
{
  int               nResult;
  int               nResultTmp;

  int               i;
  BOOL              bBreak;

  ProcessorHandler* pProcessorHandler;
  Request*          pRequest;

  nResult     = MPI_SUCCESS;
  nResultTmp  = MPI_SUCCESS;

  pThis->nSyncPositionId++;

  i       = 1; // kh 09.08.06 ignore RootMasterId 0
  bBreak  = FALSE;
  while((i < pThis->nSize) && !bBreak)
  {
    pProcessorHandler = pThis->processorHandlerPool[i];
    pRequest          = ProcessorHandler_CreateRequest(pProcessorHandler);
    nResult           = Request_InitRootMasterSyncPosition(pRequest, szPosition);

    if(nResult == MPI_SUCCESS)
    {
      nResult = Request_Send(pRequest);

      if(nResult == MPI_SUCCESS)
      {
      }
      else
      {
        if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
        {
          YBWCManager_Printf(pThis, "ERROR YBWCManager_HookPosition(... failed at Request_Send(..., errorcode = %d\n", nResult);
        }

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

// kh 09.08.06 defensive (will probably not help any more...)
//      bBreak = TRUE;  
      }
    }
    else
    {
      if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
      {
        YBWCManager_Printf(pThis, "ERROR YBWCManager_HookPosition(... failed at Request_InitRootMasterSyncPosition(..., errorcode = %d\n", nResult);
      }

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

// kh 09.08.06 defensive (will probably not help any more...)
//    bBreak = TRUE; 
    }

    i++;
  }

  nResult = nResultTmp;

  return nResult;
}

int YBWCManager_HookNewGame(YBWCManager* pThis, unsigned int nTimeout)
{
  int               nResult;
  int               nResultTmp;

  int               i;
  BOOL              bBreak;

  CountdownTimer*   pTimeoutTimer;
  CountdownTimer*   pCountdownTimer;

  ProcessorHandler* pProcessorHandler;
  Request*          pRequest;

  nResult     = MPI_SUCCESS;
  nResultTmp  = MPI_SUCCESS;

  pThis->nSyncedNewGameCount = 0;

  i       = 1; // kh 09.08.06 ignore RootMasterId 0
  bBreak  = FALSE;
  while((i < pThis->nSize) && !bBreak)
  {
    pProcessorHandler                 = pThis->processorHandlerPool[i];
    pProcessorHandler->bSyncedNewGame = FALSE;

    pRequest          = ProcessorHandler_CreateRequest(pProcessorHandler);
    nResult           = Request_InitRootMasterNewGame(pRequest);

    if(nResult == MPI_SUCCESS)
    {
      nResult = Request_Send(pRequest);

      if(nResult == MPI_SUCCESS)
      {
      }
      else
      {
        if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
        {
          YBWCManager_Printf(pThis, "ERROR YBWCManager_HookNewGame(... failed at Request_Send(..., errorcode = %d\n", nResult);
        }

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

// kh 09.08.06 defensive (will probably not help any more...)
//      bBreak = TRUE;  
      }
    }
    else
    {
      if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
      {
        YBWCManager_Printf(pThis, "ERROR YBWCManager_HookNewGame(... failed at Request_InitRootMasterNewGame(..., errorcode = %d\n", nResult);
      }

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

// kh 09.08.06 defensive (will probably not help any more...)
//    bBreak = TRUE; 
    }

    i++;
  }

  nResult = nResultTmp;

// kh 05.01.07 nTimeout == 0 will be handled as infinite (no) timeout
  pTimeoutTimer   = CountdownTimer_Construct((CountdownTimer*)malloc(sizeof(CountdownTimer)), nTimeout);
  pCountdownTimer = CountdownTimer_Construct((CountdownTimer*)malloc(sizeof(CountdownTimer)), YBWC_MANAGER_SYNC_NEW_GAME_POLL_RATE);

  if(nResult == MPI_SUCCESS)
  {
    bBreak = FALSE;
    while(!bBreak)
    {

// kh 05.01.07 YBWCManager_ServiceResults(... should be sufficient, but in the case
// a processor is sending requests already during the startup phase, internal
// buffers of the mpi environment may be blocking so YBWCManager_ServiceMessages(...
// is used for defensive reasons
      nResult = YBWCManager_ServiceMessages(pThis);

      if(nResult == MPI_SUCCESS)
      {
        if(YBWCManager_CheckAllSyncedNewGame(pThis))
        {
          bBreak = TRUE;
        }
      }
      else
      {
        if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
        {
          YBWCManager_Printf(pThis, "ERROR YBWCManager_HookNewGame(... failed at YBWCManager_ServiceMessages(..., errorcode = %d\n", nResult);
        }
        bBreak = TRUE;
      }

      if(!bBreak)
      {
        if((nTimeout == 0) || CountdownTimer_IsRunning(pTimeoutTimer))
        {
          CountdownTimer_WaitAndRestart(pCountdownTimer);
  //      Beep(1000, 50);
        }
        else
        {
          if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_WARNING_PRIO_1)
          {
            YBWCManager_Printf(pThis, "WARNING YBWCManager_HookNewGame(... time out while waiting for non root master sync \n");
          }
          bBreak = TRUE;
        }
      }
    }
  }

  CountdownTimer_Destruct(pCountdownTimer);
  CountdownTimer_Destruct(pTimeoutTimer);

  return nResult;
}

int YBWCManager_HookSetOption(YBWCManager* pThis, unsigned int nTimeout, char* szOptionName, char* szOptionValue)
{
  int               nResult;
  int               nResultTmp;

  int               i;
  BOOL              bBreak;

  CountdownTimer*   pTimeoutTimer;
  CountdownTimer*   pCountdownTimer;

  ProcessorHandler* pProcessorHandler;
  Request*          pRequest;

  nResult     = MPI_SUCCESS;
  nResultTmp  = MPI_SUCCESS;

  pThis->nSyncedSetOptionCount = 0;

  i       = 1; // kh 09.08.06 ignore RootMasterId 0
  bBreak  = FALSE;
  while((i < pThis->nSize) && !bBreak)
  {
    pProcessorHandler                   = pThis->processorHandlerPool[i];
    pProcessorHandler->bSyncedSetOption = FALSE;

    pRequest          = ProcessorHandler_CreateRequest(pProcessorHandler);
    nResult           = Request_InitRootMasterSetOption(pRequest, szOptionName, szOptionValue);

    if(nResult == MPI_SUCCESS)
    {
      nResult = Request_Send(pRequest);

      if(nResult == MPI_SUCCESS)
      {
      }
      else
      {
        if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
        {
          YBWCManager_Printf(pThis, "ERROR YBWCManager_HookSetOption(... failed at Request_Send(..., errorcode = %d\n", nResult);
        }

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

// kh 07.02.08 defensive (will probably not help any more...)
//      bBreak = TRUE;  
      }
    }
    else
    {
      if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
      {
        YBWCManager_Printf(pThis, "ERROR YBWCManager_HookSetOption(... failed at Request_InitRootMasterSetOption(..., errorcode = %d\n", nResult);
      }

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

// kh 07.02.08 defensive (will probably not help any more...)
//    bBreak = TRUE; 
    }

    i++;
  }

  nResult = nResultTmp;

// kh 07.02.08 nTimeout == 0 will be handled as infinite (no) timeout
  pTimeoutTimer   = CountdownTimer_Construct((CountdownTimer*)malloc(sizeof(CountdownTimer)), nTimeout);
  pCountdownTimer = CountdownTimer_Construct((CountdownTimer*)malloc(sizeof(CountdownTimer)), YBWC_MANAGER_SYNC_SET_OPTION_POLL_RATE);

  if(nResult == MPI_SUCCESS)
  {
    bBreak = FALSE;
    while(!bBreak)
    {

// kh 07.02.08 YBWCManager_ServiceResults(... should be sufficient, but in the case
// a processor is sending requests already during the startup phase, internal
// buffers of the mpi environment may be blocking so YBWCManager_ServiceMessages(...
// is used for defensive reasons
      nResult = YBWCManager_ServiceMessages(pThis);

      if(nResult == MPI_SUCCESS)
      {
        if(YBWCManager_CheckAllSyncedSetOption(pThis))
        {
          bBreak = TRUE;
        }
      }
      else
      {
        if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
        {
          YBWCManager_Printf(pThis, "ERROR YBWCManager_HookSetOption(... failed at YBWCManager_ServiceMessages(..., errorcode = %d\n", nResult);
        }
        bBreak = TRUE;
      }

      if(!bBreak)
      {
        if((nTimeout == 0) || CountdownTimer_IsRunning(pTimeoutTimer))
        {
          CountdownTimer_WaitAndRestart(pCountdownTimer);
  //      Beep(1000, 50);
        }
        else
        {
          if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_WARNING_PRIO_1)
          {
            YBWCManager_Printf(pThis, "WARNING YBWCManager_HookSetOption(... time out while waiting for non root master sync \n");
          }
          bBreak = TRUE;
        }
      }
    }
  }

  CountdownTimer_Destruct(pCountdownTimer);
  CountdownTimer_Destruct(pTimeoutTimer);

  return nResult;
}

int YBWCManager_WaitForSyncAfterBroadcast(YBWCManager* pThis, unsigned int nTimeout)
{
  int               nResult;
  int               nResultTmp;

  int               i;
  BOOL              bBreak;

  CountdownTimer*   pTimeoutTimer;
  CountdownTimer*   pCountdownTimer;

  ProcessorHandler* pProcessorHandler;
  Request*          pRequest;

  nResult     = MPI_SUCCESS;
  nResultTmp  = MPI_SUCCESS;

// kh 07.02.08 used especially to synchronize the hash table access during resize and shutdown
// since the root- and the non root masters broadcast (replicate) permanently their hash table content
// there may exist not yet processed requests for the actual non root master (other non root master or the root master)
// the idea is here that each non root master waits until all of its broadcasted info has been processed by all 
// other processors. 
  pThis->nSyncedAfterBroadcastCount = 0;

  i       = 0; // kh 07.02.08 do not ignore RootMasterId 0
  bBreak  = FALSE;
  while((i < pThis->nSize) && !bBreak)
  {
    if(i == pThis->nRank)
    {
      // kh 07.02.08 skip
    } // if(i == pThis->nRank)
    else
    {
      pProcessorHandler                        = pThis->processorHandlerPool[i];
      pProcessorHandler->bSyncedAfterBroadcast = FALSE;

      pRequest          = ProcessorHandler_CreateRequest(pProcessorHandler);
      nResult           = Request_InitNonRootMasterSyncAfterBroadcast(pRequest);

      if(nResult == MPI_SUCCESS)
      {
        nResult = Request_Send(pRequest);

        if(nResult == MPI_SUCCESS)
        {
        }
        else
        {
          if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
          {
            YBWCManager_Printf(pThis, "ERROR YBWCManager_WaitForSyncAfterBroadcast(... failed at Request_Send(..., errorcode = %d\n", nResult);
          }

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

  // kh 07.02.08 defensive (will probably not help any more...)
  //      bBreak = TRUE;  
        }
      }
      else
      {
        if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
        {
          YBWCManager_Printf(pThis, "ERROR YBWCManager_WaitForSyncAfterBroadcast(... failed at Request_InitNonRootMasterSyncAfterBroadcast(..., errorcode = %d\n", nResult);
        }

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

// kh 07.02.08 defensive (will probably not help any more...)
//    bBreak = TRUE; 
      }
    } // !if(i == pThis->nRank)

    i++;
  }

  nResult = nResultTmp;

// kh 07.02.08 nTimeout == 0 will be handled as infinite (no) timeout
  pTimeoutTimer   = CountdownTimer_Construct((CountdownTimer*)malloc(sizeof(CountdownTimer)), nTimeout);
  pCountdownTimer = CountdownTimer_Construct((CountdownTimer*)malloc(sizeof(CountdownTimer)), YBWC_MANAGER_SYNC_AFTER_BROADCAST_POLL_RATE);

  if(nResult == MPI_SUCCESS)
  {
    bBreak = FALSE;
    while(!bBreak)
    {

// kh 07.02.08 YBWCManager_ServiceResults(... should be sufficient, but in the case
// a processor is sending requests already during the startup phase, internal
// buffers of the mpi environment may be blocking so YBWCManager_ServiceMessages(...
// is used for defensive reasons
      nResult = YBWCManager_ServiceMessages(pThis);

      if(nResult == MPI_SUCCESS)
      {
        if(YBWCManager_CheckAllSyncedAfterBroadcast(pThis))
        {
          bBreak = TRUE;
        }
      }
      else
      {
        if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
        {
          YBWCManager_Printf(pThis, "ERROR YBWCManager_WaitForSyncAfterBroadcast(... failed at YBWCManager_ServiceMessages(..., errorcode = %d\n", nResult);
        }
        bBreak = TRUE;
      }

      if(!bBreak)
      {
        if((nTimeout == 0) || CountdownTimer_IsRunning(pTimeoutTimer))
        {
          CountdownTimer_WaitAndRestart(pCountdownTimer);
  //      Beep(1000, 50);
        }
        else
        {
          if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_WARNING_PRIO_1)
          {
            YBWCManager_Printf(pThis, "WARNING YBWCManager_WaitForSyncAfterBroadcast(... time out while waiting for sync \n");
          }
          bBreak = TRUE;
        }
      }
    }
  }

  CountdownTimer_Destruct(pCountdownTimer);
  CountdownTimer_Destruct(pTimeoutTimer);

  return nResult;
}

int YBWCManager_HookRemoteTest(YBWCManager* pThis, int nId, char* szGoCommands)
{
  int               nResult;

  ProcessorHandler* pProcessorHandler;
  Request*          pRequest;

  nResult = MPI_SUCCESS;

  pThis->nRemoteTestProcessorId = nId;
  pProcessorHandler             = pThis->processorHandlerPool[nId];
  pRequest                      = ProcessorHandler_CreateRequest(pProcessorHandler);
  nResult                       = Request_InitRootMasterRemoteTest(pRequest, szGoCommands);

  if(nResult == MPI_SUCCESS)
  {
    nResult = Request_Send(pRequest);

    if(nResult == MPI_SUCCESS)
    {
    }
    else
    {
      if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
      {
        YBWCManager_Printf(pThis, "ERROR YBWCManager_HookRemoteTest(... failed at Request_Send(..., errorcode = %d\n", nResult);
      }
    }
  }
  else
  {
    if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
    {
      YBWCManager_Printf(pThis, "ERROR YBWCManager_HookRemoteTest(... failed at Request_InitRootMasterRemoteTest(..., errorcode = %d\n", nResult);
    }
  }

  return nResult;
}

int YBWCManager_HookStop(YBWCManager* pThis)
{
  int               nResult;

  ProcessorHandler* pProcessorHandler;
  Request*          pRequest;

  nResult = MPI_SUCCESS;

// kh 05.09.06 explicit stopping of a non root master is only needed for an active remote test at the moment
  if(pThis->nState == YBWC_MANAGER_STATE_SEARCHING_REMOTE)
  {
    ASSERT(pThis->nRemoteTestProcessorId > 0);

    pProcessorHandler = pThis->processorHandlerPool[pThis->nRemoteTestProcessorId];
    pRequest          = ProcessorHandler_CreateRequest(pProcessorHandler);
    nResult           = Request_InitRootMasterStopRemoteSearch(pRequest);

    if(nResult == MPI_SUCCESS)
    {
      nResult = Request_Send(pRequest);

      if(nResult == MPI_SUCCESS)
      {
      }
      else
      {
        if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
        {
          YBWCManager_Printf(pThis, "ERROR YBWCManager_HookStop(... failed at Request_Send(..., errorcode = %d\n", nResult);
        }
      }
    }
    else
    {
      if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
      {
        YBWCManager_Printf(pThis, "ERROR YBWCManager_HookRemoteTest(... failed at Request_InitRootMasterRemoteTest(..., errorcode = %d\n", nResult);
      }
    }
  }
  else
  {

// kh 12.09.06 as a future expansion uci stop may be broadcasted here as a "forced stop"
// to all non root master for a better performance

  }

  return nResult;
}


uint64 YBWCManager_CalcRootNodeSlavesTransUsed(YBWCManager* pThis)
{
  uint64            nResult;

  ProcessorHandler* pProcessorHandler;

  int               i;

  nResult = 0;

  i       = 1; // kh 25.03.08 ignore RootMasterId 0
  while(i < pThis->nSize)
  {
    pProcessorHandler = pThis->processorHandlerPool[i];

    if(strcmp(pProcessorHandler->sProcessorName, pThis->sProcessorName) == 0)
    {
      // kh 25.03.08 this process runs on the same node as the root master
      nResult += pProcessorHandler->nTransUsed;
    }

    i++;
  }

  return nResult;
}

int YBWCManager_HookGo(YBWCManager* pThis)
{
  int               nResult;
  int               nResultTmp;

  int               i;
  BOOL              bBreak;

  ProcessorHandler* pProcessorHandler;
  Request*          pRequest;

  nResult     = MPI_SUCCESS;
  nResultTmp  = MPI_SUCCESS;

  i       = 1; // kh 06.09.06 ignore RootMasterId 0
  bBreak  = FALSE;
  while((i < pThis->nSize) && !bBreak)
  {
    pProcessorHandler             = pThis->processorHandlerPool[i];
    pProcessorHandler->nTransUsed = 0;
    pRequest                      = ProcessorHandler_CreateRequest(pProcessorHandler);
    nResult                       = Request_InitRootMasterSupportSearch(pRequest);

    if(nResult == MPI_SUCCESS)
    {
      nResult = Request_Send(pRequest);

      if(nResult == MPI_SUCCESS)
      {
      }
      else
      {
        if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
        {
          YBWCManager_Printf(pThis, "ERROR YBWCManager_HookGo(... failed at Request_Send(..., errorcode = %d\n", nResult);
        }

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

// kh 06.09.06 defensive (will probably not help any more...)
//      bBreak = TRUE;  
      }
    }
    else
    {
      if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
      {
        YBWCManager_Printf(pThis, "ERROR YBWCManager_HookGo(... failed at Request_InitRootMasterSupportSearch(..., errorcode = %d\n", nResult);
      }

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

// kh 06.09.06 defensive (will probably not help any more...)
//    bBreak = TRUE; 
    }

    i++;
  }

  nResult = nResultTmp;

  return nResult;
}

int YBWCManager_HookSearchTerminated(YBWCManager* pThis)
{
  int               nResult;
  int               nResultTmp;

  int               i;
  BOOL              bBreak;

  ProcessorHandler* pProcessorHandler;
  Request*          pRequest;

  nResult     = MPI_SUCCESS;
  nResultTmp  = MPI_SUCCESS;

  i       = 1; // kh 20.09.06 ignore RootMasterId 0
  bBreak  = FALSE;
  while((i < pThis->nSize) && !bBreak)
  {
    pProcessorHandler = pThis->processorHandlerPool[i];
    pRequest          = ProcessorHandler_CreateRequest(pProcessorHandler);
    nResult           = Request_InitRootMasterIdleInvitation(pRequest);

    if(nResult == MPI_SUCCESS)
    {
      nResult = Request_Send(pRequest);

      if(nResult == MPI_SUCCESS)
      {
      }
      else
      {
        if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
        {
          YBWCManager_Printf(pThis, "ERROR YBWCManager_HookSearchTerminated(... failed at Request_Send(..., errorcode = %d\n", nResult);
        }

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

// kh 20.09.06 defensive (will probably not help any more...)
//      bBreak = TRUE;  
      }
    }
    else
    {
      if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
      {
        YBWCManager_Printf(pThis, "ERROR YBWCManager_HookSearchTerminated(... failed at Request_InitRootMasterIdleInvitation(..., errorcode = %d\n", nResult);
      }

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

// kh 20.09.06 defensive (will probably not help any more...)
//    bBreak = TRUE; 
    }

    i++;
  }

  nResult = nResultTmp;

  return nResult;
}

char* YBWCManager_InitSharedMem(YBWCManager* pThis, int nSharedMemoryKey, int nTotalSize)
{
#if defined(_WIN32) || defined(_WIN64)

  char*   pcResult;
  char    szTableName[512];

  char    szDrive [_MAX_DRIVE];
  char    szDir   [_MAX_DIR]; 
  char    szFName [_MAX_FNAME];
  char    szExt   [_MAX_EXT];

  bool    bAllocacted;

  HANDLE  hMapObject;

  _splitpath((*pThis->pargv)[0], szDrive, szDir, szFName, szExt);

//sprintf(szTableName, "SharedMemory_Id_%d", nSharedMemoryKey);
  sprintf(szTableName, "SharedMemory_Id_%s_%d", szFName, nSharedMemoryKey);

  bAllocacted = false;

  if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_FORCE_OUTPUT)
  {
    YBWCManager_Printf(pThis, 
                       "INFO shared memory for key %d (map object name %s), size desired = %d\n", 
                       nSharedMemoryKey,
                       szTableName,
                       nTotalSize);
  }

  hMapObject = CreateFileMapping(INVALID_HANDLE_VALUE, // use paging file
                                 NULL,                 // no security attributes
                                 PAGE_READWRITE,       // read/write access
                                 0,                    // size: high 32-bits
                                 nTotalSize,           // size: low 32-bits
                                 szTableName);         // name of map object

  if(hMapObject)
  {
    bAllocacted = true;
    if(GetLastError() == ERROR_ALREADY_EXISTS)
    {
      bAllocacted = false;

      switch(nSharedMemoryKey)
      {
      case SHARED_MEMORY_KEY_TRANSPOSITION_TABLE:
		    if(pThis->pSharedTranspositionTable) // kh 22.11.07 free old table, defensive
		    {

// kh 28.11.07 for debug purposes only
/*
  	      YBWCManager_SaveLogSettings(pThis, LogSettings_Instance());

          pThis->pFruitConfiguration->bLogToFile = TRUE;
          YBWCManager_Printf(pThis, "UnmapViewOfFile(pThis->pSharedTranspositionTable)...\n");
*/

			    if(UnmapViewOfFile(pThis->pSharedTranspositionTable))
			    {
			      CloseHandle(pThis->hMapSharedTranspositionTable);

// kh 16.02.07 force output at the moment
			      if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_FORCE_OUTPUT)
		  	    {
			        YBWCManager_Printf(pThis, "INFO successful detach (without delete) of shared memory for transposition table\n");
			      }
			    } // if(UnmapViewOfFile(pThis->pSharedTranspositionTable))
			    else
			    {
			      if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_FORCE_OUTPUT)
			      {
				      YBWCManager_Printf(pThis, "INFO detach of shared memory for transposition table failed\n");
			      }
			    } // !if(UnmapViewOfFile(pThis->pSharedTranspositionTable))

// kh 28.11.07 for debug purposes only
/*
          YBWCManager_LoadLogSettings(pThis, LogSettings_Instance());
*/

		    } // if(pThis->pSharedTranspositionTable)

        pThis->nSharedTranspositionTableAttachType  = SHARED_MEMORY_ATTACH_TYPE_USER;
        pThis->hMapSharedTranspositionTable         = hMapObject;
        break;

      case SHARED_MEMORY_KEY_HISTORY_TABLE:
		    if(pThis->pSharedHistoryTable)
		    {
			    if(UnmapViewOfFile(pThis->pSharedHistoryTable))
			    {
			      CloseHandle(pThis->hMapSharedHistoryTable);

// kh 16.02.07 force output at the moment
				    if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_FORCE_OUTPUT)
				    {
				      YBWCManager_Printf(pThis, "INFO successful detach (without delete) of shared memory for history table\n");
				    }
			    } // if(UnmapViewOfFile(pThis->pSharedHistoryTable))
			    else
			    {
			      if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_FORCE_OUTPUT)
			      {
				      YBWCManager_Printf(pThis, "INFO detach of shared memory for history table failed\n");
			      }
			    } // !if(UnmapViewOfFile(pThis->pSharedHistoryTable))
		    } // if(pThis->pSharedHistoryTable)

        pThis->nSharedHistoryTableAttachType        = SHARED_MEMORY_ATTACH_TYPE_USER;
        pThis->hMapSharedHistoryTable               = hMapObject;
        break;

      default:
        ASSERT(false);
        break;
      }

// kh 13.02.07 force output at the moment
      if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_FORCE_OUTPUT)
      {
        YBWCManager_Printf(pThis, 
                           "INFO shared memory for key %d (map object name %s) with size %d already allocated\n", 
                           nSharedMemoryKey,
                           szTableName,
                           nTotalSize);
      }
    }

// kh 13.02.07 get a pointer to the file-mapped shared memory
    pcResult = (char*)MapViewOfFile(hMapObject,     // object to map view of
                                    FILE_MAP_WRITE, // read/write access
                                    0,              // high offset:  map from
                                    0,              // low offset:   beginning
                                    0);             // default: map entire file

    if(pcResult) 
    {

//    memset(pcResult, '\0', nTotalSize);

      switch(nSharedMemoryKey)
      {
      case SHARED_MEMORY_KEY_TRANSPOSITION_TABLE:
        pThis->pSharedTranspositionTable = pcResult;
        break;

      case SHARED_MEMORY_KEY_HISTORY_TABLE:
        pThis->pSharedHistoryTable       = pcResult;
        break;

      default:
        ASSERT(false);
        break;
      }

      if(bAllocacted)
      {
        switch(nSharedMemoryKey)
        {
        case SHARED_MEMORY_KEY_TRANSPOSITION_TABLE:
          pThis->nSharedTranspositionTableAttachType  = SHARED_MEMORY_ATTACH_TYPE_OWNER;
          pThis->hMapSharedTranspositionTable         = hMapObject;
          break;

        case SHARED_MEMORY_KEY_HISTORY_TABLE:
          pThis->nSharedHistoryTableAttachType        = SHARED_MEMORY_ATTACH_TYPE_OWNER;
          pThis->hMapSharedHistoryTable               = hMapObject;
          break;

        default:
          ASSERT(false);
          break;
        }

// kh 13.02.07 force output at the moment 
        if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_FORCE_OUTPUT)
        {
          YBWCManager_Printf(pThis, 
                             "INFO shared memory for key %d (map object name %s) with size %d successfully allocated\n",
                             nSharedMemoryKey,
                             szTableName,
                             nTotalSize);
        }
      }
    }
    else
    {
      if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
      {
        YBWCManager_Printf(pThis, 
                           "ERROR YBWCManager_InitSharedMem(... failed at pcResult = MapViewOfFile(hMapObject, FILE_MAP_WRITE, , 0, 0, 0)), result = %d\n",
                           GetLastError());
      }

      CloseHandle(hMapObject); 
    } 
  }
  else
  {
    if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
    {
      YBWCManager_Printf(pThis, 
                         "ERROR YBWCManager_InitSharedMem(... failed at hMapObject = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, %d, %s)), result = %d\n",
                         nTotalSize,
                         szTableName,
                         GetLastError());
    }
  }

  return pcResult;

#else // assume POSIX

  char* pcResult;
  int   nSharedMemoryId;

  pcResult        = NULL;
  nSharedMemoryId = 0;

// In case of a shared hashtbl, every process gets the same Table-Name.
//int key = (ParamTbl[PRM_SHAREDHASH]) ? KEYBASEVAL:KEYBASEVAL + pThis->nRank;
// kh 13.12.06 force output at the moment 

  if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_FORCE_OUTPUT)
  {
    YBWCManager_Printf(pThis, 
                       "INFO shared memory for key %d, size desired = %d\n", 
                       nSharedMemoryKey,
                       nTotalSize);
  }

//-- Open the shared memory segment - create if necessary

  if((nSharedMemoryId = shmget(nSharedMemoryKey, nTotalSize, IPC_CREAT | IPC_EXCL | SVSHM_MODE)) == -1) 
  {
// Segment probably already exists - try as a client

    if((nSharedMemoryId = shmget(nSharedMemoryKey, nTotalSize, IPC_CREAT | SVSHM_MODE)) == -1) 
    {
      if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
      {
        YBWCManager_Printf(pThis, 
                           "ERROR YBWCManager_InitSharedMem(... failed at (nSharedMemoryId = shmget(%d, %d, IPC_CREAT | SVSHM_MODE)), result = -1\n",
                           nSharedMemoryKey, 
                           nTotalSize);
      }
      return NULL;
    }
    else
    {
      switch(nSharedMemoryKey)
      {
      case SHARED_MEMORY_KEY_TRANSPOSITION_TABLE:
        pThis->nSharedTranspositionTableAttachType  = SHARED_MEMORY_ATTACH_TYPE_USER;
        pThis->nSharedTranspositionTableMemoryId    = nSharedMemoryId;
        break;

      case SHARED_MEMORY_KEY_HISTORY_TABLE:
        pThis->nSharedHistoryTableAttachType        = SHARED_MEMORY_ATTACH_TYPE_USER;
        pThis->nSharedHistoryTableMemoryId          = nSharedMemoryId;
        break;

      default:
        ASSERT(false);
        break;
      }

// kh 13.12.06 force output at the moment 
      if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_FORCE_OUTPUT)
      {
        YBWCManager_Printf(pThis, 
                           "INFO shared memory for key %d with size %d probably already allocated\n", 
                           nSharedMemoryKey,
                           nTotalSize);
      }
    }
  } // if((nSharedMemoryId = shmget(nSharedMemoryKey, nTotalSize, IPC_CREAT | IPC_EXCL | SVSHM_MODE)) == -1) 
  else
  {
    switch(nSharedMemoryKey)
    {
    case SHARED_MEMORY_KEY_TRANSPOSITION_TABLE:
      pThis->nSharedTranspositionTableAttachType  = SHARED_MEMORY_ATTACH_TYPE_OWNER;
      pThis->nSharedTranspositionTableMemoryId    = nSharedMemoryId;
      break;

    case SHARED_MEMORY_KEY_HISTORY_TABLE:
      pThis->nSharedHistoryTableAttachType        = SHARED_MEMORY_ATTACH_TYPE_OWNER;
      pThis->nSharedHistoryTableMemoryId          = nSharedMemoryId;
      break;

    default:
      ASSERT(false);
      break;
    }

// kh 13.12.06 force output at the moment 
    if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_FORCE_OUTPUT)
    {
      YBWCManager_Printf(pThis, 
                         "INFO shared memory for key %d with size %d successfully allocated\n",
                         nSharedMemoryKey,
                         nTotalSize);
    }
  } // !if((nSharedMemoryId = shmget(nSharedMemoryKey, nTotalSize, IPC_CREAT | IPC_EXCL | SVSHM_MODE)) == -1) 

   //-- Attach (map) the shared memory segment into the current process
  if((pcResult = (char*)shmat(nSharedMemoryId, 0, 0)) == MAP_FAILED) 
  {
    if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
    {
      YBWCManager_Printf(pThis, 
                         "ERROR YBWCManager_InitSharedMem(... failed at (pcResult = shmat(%d, %d, 0, 0)), result = MAP_FAILED\n",
                         nSharedMemoryKey,
                         nTotalSize);
    }
  }
  else
  {
    switch(nSharedMemoryKey)
    {
    case SHARED_MEMORY_KEY_TRANSPOSITION_TABLE:
      pThis->pSharedTranspositionTable = pcResult;
      break;

    case SHARED_MEMORY_KEY_HISTORY_TABLE:
      pThis->pSharedHistoryTable       = pcResult;
      break;

    default:
      ASSERT(false);
      break;
    }

// kh 13.12.06 force output at the moment 
    if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_FORCE_OUTPUT)
    {
      YBWCManager_Printf(pThis, 
                         "INFO shared memory for key %d with size %d successfully attached\n",
                         nSharedMemoryKey,
                         nTotalSize);
    }
  }

  return pcResult;

#endif
}

void YBWCManager_DetachSharedMem(YBWCManager* pThis, int nSharedMemoryKey)
{

#if defined(_WIN32) || defined(_WIN64)
  int     nSharedMemoryAttachType;
  void*   pMapObject;
  HANDLE  hMapObject;

  nSharedMemoryAttachType = SHARED_MEMORY_ATTACH_TYPE_NONE;
  switch(nSharedMemoryKey)
  {
  case SHARED_MEMORY_KEY_TRANSPOSITION_TABLE:
    nSharedMemoryAttachType = pThis->nSharedTranspositionTableAttachType;
    pMapObject              = pThis->pSharedTranspositionTable;
    hMapObject              = pThis->hMapSharedTranspositionTable;
    break;

  case SHARED_MEMORY_KEY_HISTORY_TABLE:
    nSharedMemoryAttachType = pThis->nSharedHistoryTableAttachType;
    pMapObject              = pThis->pSharedHistoryTable;
    hMapObject              = pThis->hMapSharedHistoryTable;
    break;

  default:
    ASSERT(false);
    break;
  }

  if(nSharedMemoryAttachType == SHARED_MEMORY_ATTACH_TYPE_USER)
  {
    if(UnmapViewOfFile(pMapObject))
    {
      CloseHandle(hMapObject);

// kh 16.02.07 force output at the moment
      if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_FORCE_OUTPUT)
      {
        YBWCManager_Printf(pThis, 
                           "INFO successful detach (without delete) of shared memory for key %d\n",
                           nSharedMemoryKey);
      }
    } // if(UnmapViewOfFile(hMapObject))
    else
    {
      if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_FORCE_OUTPUT)
      {
        YBWCManager_Printf(pThis, 
                           "ERROR detach of shared memory for key %d failed\n",
                           nSharedMemoryKey);
      }
    } // !if(UnmapViewOfFile(hMapObject))
  } // if(nSharedMemoryAttachType == SHARED_MEMORY_ATTACH_TYPE_USER)

#else // assume POSIX

// kh 08.02.08 in case of problems use "./cleanipcs" from the command line additionally
// kh 11.02.08 known issue: memory is not deleted until process exit

  int   nSharedMemoryAttachType;
  void* pSharedMem;

  nSharedMemoryAttachType = SHARED_MEMORY_ATTACH_TYPE_NONE;
  switch(nSharedMemoryKey)
  {
  case SHARED_MEMORY_KEY_TRANSPOSITION_TABLE:
    nSharedMemoryAttachType = pThis->nSharedTranspositionTableAttachType;
    pSharedMem              = pThis->pSharedTranspositionTable;
    break;

  case SHARED_MEMORY_KEY_HISTORY_TABLE:
    nSharedMemoryAttachType = pThis->nSharedHistoryTableAttachType;
    pSharedMem              = pThis->pSharedHistoryTable;
    break;

  default:
    ASSERT(false);
    break;
  }

  if(nSharedMemoryAttachType == SHARED_MEMORY_ATTACH_TYPE_USER)
  {
    if(shmdt(pSharedMem) == -1) 
    {
      if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_FORCE_OUTPUT)
      {
        YBWCManager_Printf(pThis, 
                           "ERROR detach of shared memory for key %d failed at shmdt(%d)\n",
                           nSharedMemoryKey,
                           pSharedMem);
      }
    }
    else
    {
      if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_FORCE_OUTPUT)
      {
        YBWCManager_Printf(pThis, 
                           "INFO successful detach (without delete) of shared memory for key %d\n",
                           nSharedMemoryKey);
      }
    }
  }

#endif
}

void YBWCManager_DetachSharedMemAll(YBWCManager* pThis)
{
  YBWCManager_DetachSharedMem(pThis, SHARED_MEMORY_KEY_TRANSPOSITION_TABLE);
  YBWCManager_DetachSharedMem(pThis, SHARED_MEMORY_KEY_HISTORY_TABLE);
}

void YBWCManager_DeleteSharedMem(YBWCManager* pThis, int nSharedMemoryKey)
{
#if defined(_WIN32) || defined(_WIN64)
  int     nSharedMemoryAttachType;
  void*   pMapObject;
  HANDLE  hMapObject;

  nSharedMemoryAttachType = SHARED_MEMORY_ATTACH_TYPE_NONE;
  switch(nSharedMemoryKey)
  {
  case SHARED_MEMORY_KEY_TRANSPOSITION_TABLE:
    nSharedMemoryAttachType = pThis->nSharedTranspositionTableAttachType;
    pMapObject              = pThis->pSharedTranspositionTable;
    hMapObject              = pThis->hMapSharedTranspositionTable;
    break;

  case SHARED_MEMORY_KEY_HISTORY_TABLE:
    nSharedMemoryAttachType = pThis->nSharedHistoryTableAttachType;
    pMapObject              = pThis->pSharedHistoryTable;
    hMapObject              = pThis->hMapSharedHistoryTable;
    break;

  default:
    ASSERT(false);
    break;
  }

  if(nSharedMemoryAttachType == SHARED_MEMORY_ATTACH_TYPE_OWNER)
  {
    if(UnmapViewOfFile(pMapObject))
    {
      CloseHandle(hMapObject);

// kh 16.02.07 force output at the moment
      if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_FORCE_OUTPUT)
      {
        if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_FORCE_OUTPUT)
        {
          YBWCManager_Printf(pThis, 
                             "INFO successful detach and delete of shared memory for key %d\n",
                             nSharedMemoryKey);
        }
      }
    } // if(UnmapViewOfFile(pThis->pSharedTranspositionTable))
    else
    {
      if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_FORCE_OUTPUT)
      {
        YBWCManager_Printf(pThis, 
                           "ERROR detach and delete of shared memory for key %d failed\n",
                           nSharedMemoryKey);
      }
    } // !if(UnmapViewOfFile(pThis->pSharedTranspositionTable))
  } // if(nSharedMemoryAttachType == SHARED_MEMORY_ATTACH_TYPE_OWNER)

#else // assume POSIX

// kh 08.02.08 in case of problems use "./cleanipcs" from the command line additionally
// kh 11.02.08 known issue: memory is not deleted until process exit

  int     nSharedMemoryAttachType;
  int     nSharedMemoryId;
  struct  shmid_ds Shmidds;

  nSharedMemoryAttachType = SHARED_MEMORY_ATTACH_TYPE_NONE;
  switch(nSharedMemoryKey)
  {
  case SHARED_MEMORY_KEY_TRANSPOSITION_TABLE:
    nSharedMemoryAttachType = pThis->nSharedTranspositionTableAttachType;
    nSharedMemoryId         = pThis->nSharedTranspositionTableMemoryId;
    break;

  case SHARED_MEMORY_KEY_HISTORY_TABLE:
    nSharedMemoryAttachType = pThis->nSharedHistoryTableAttachType;
    nSharedMemoryId         = pThis->nSharedHistoryTableMemoryId;
    break;

  default:
    ASSERT(false);
    break;
  }

  if(nSharedMemoryAttachType == SHARED_MEMORY_ATTACH_TYPE_OWNER)
  {
    if(shmctl(nSharedMemoryId, IPC_RMID, &Shmidds) == -1) 
    {
      if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_FORCE_OUTPUT)
      {
        YBWCManager_Printf(pThis, 
                           "ERROR delete of shared memory for key %d failed at shmctl(%d, IPC_RMID, &Shmidds)\n",
                           nSharedMemoryKey,
                           nSharedMemoryId);
      }
    }
    else
    {
      if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_FORCE_OUTPUT)
      {
        YBWCManager_Printf(pThis, 
                           "INFO successful delete of shared memory for key %d and id %d \n",
                           nSharedMemoryKey,
                           nSharedMemoryId);
      }
    }
  }

#endif
}

void YBWCManager_DeleteSharedMemAll(YBWCManager* pThis)
{
  YBWCManager_DeleteSharedMem(pThis, SHARED_MEMORY_KEY_TRANSPOSITION_TABLE);
  YBWCManager_DeleteSharedMem(pThis, SHARED_MEMORY_KEY_HISTORY_TABLE);
}

int YBWCManager_BroadcastHistoryTable(YBWCManager* pThis)
{
  int               nResult;
  int               nResultTmp;

  int               i;
  BOOL              bBreak;

  ProcessorHandler* pProcessorHandler;
  Request*          pRequest;

  nResult     = MPI_SUCCESS;
  nResultTmp  = MPI_SUCCESS;

  ASSERT(!pThis->pHistoryTableBroadcastRequestBuffer);

  if(pThis->pHistoryTableBroadcastRequestBuffer == NULL)
  {
    pThis->pHistoryTableBroadcastRequestBuffer = Request_Construct((Request*)malloc(sizeof(Request)));
    nResult = Request_InitHistoryTableBroadcastBuffer(pThis->pHistoryTableBroadcastRequestBuffer);
    if(nResult == MPI_SUCCESS)
    {
      for(i = 0; i < HistorySize; i++) 
      {
        pThis->HistoryTableBuffer[i] = 0;
      }

      pThis->nHistoryUpdateCount = 0;
    }
    else
    {
      if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
      {
        YBWCManager_Printf(pThis, "ERROR YBWCManager_BroadcastHistoryTable(... failed at Request_InitHistoryTableBroadcastBuffer(..., errorcode = %d\n", nResult);
      }
    }
  } // if(pThis->pHistoryTableBroadcastRequestBuffer == NULL)

  ASSERT(pThis->pHistoryTableBroadcastRequestBuffer);
  ASSERT(pThis->pHistoryTableBroadcastRequestBuffer->nReferenceCount == 0);

  pThis->pHistoryTableBroadcastRequestBuffer->bPreventDestruct = TRUE;

  i       = 0; // kh 20.02.07 do not ignore RootMasterId 0
  bBreak  = FALSE;
  while((i < pThis->nSize) && !bBreak)
  {
    if(i == pThis->nRank)
    {
      // kh 20.02.07 skip
    } // if(i == pThis->nRank)
    else
    {
      pProcessorHandler = pThis->processorHandlerPool[i];
      if(pProcessorHandler->bHistoryTableBroadcastTarget || !pThis->pFruitConfiguration->bUseSharedMemoryHistoryTable)
      {
        if(pProcessorHandler->nBufferedRequestCount < 1 || true) // kh 20.02.07 do not limit the bandwidth at the moment
        {

// kh 20.02.07 pHistoryTableBroadcastRequestBuffer->nReferenceCount is potentially already decremented here
// via the cleanup for completed sends
// to prevent the deletion of pBroadcastRequestBuffer when reaching eventually a reference count of 0 in between
// a lock flag is used
          pRequest          = ProcessorHandler_CreateRequest(pProcessorHandler);

// kh 20.02.07 pHistoryTableBroadcastRequestBuffer->nReferenceCount is incremented here
          nResult           = Request_InitHistoryTableReplication(pRequest, pThis->pHistoryTableBroadcastRequestBuffer); 

          if(nResult == MPI_SUCCESS)
          {
            nResult = Request_SendBroadcastBuffer(pRequest);

            if(nResult == MPI_SUCCESS)
            {
            }
            else
            {
              if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
              {
                YBWCManager_Printf(pThis, "ERROR YBWCManager_BroadcastHistoryTable(... failed at Request_SendBroadcastBuffer(..., errorcode = %d\n", nResult);
              }

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

// kh 20.02.07 defensive 
//            bBreak = TRUE;  
            }
          } // if(nResult == MPI_SUCCESS)
          else
          {
            if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
            {
              YBWCManager_Printf(pThis, "ERROR YBWCManager_BroadcastHistoryTable(... failed at Request_InitHashTableReplication(..., errorcode = %d\n", nResult);
            }

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

// kh 20.02.07 defensive
//          bBreak = TRUE; 
          } // !if(nResult == MPI_SUCCESS)
        } // if(pProcessorHandler->nBufferedRequestCount < 1 || true)
        else
        {
          if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_INFO_PRIO_2)
          {
            YBWCManager_Printf(pThis, 
                               "YBWCManager_BroadcastHistoryTable(... nBufferedRequestCount for ProcessorHandler <%d> is still %d, send is suppressed\n",
                               pProcessorHandler->nId,
                               pProcessorHandler->nBufferedRequestCount);
          }
        } // !if(pProcessorHandler->nBufferedRequestCount < 1 || true)
      } // if(pProcessorHandler->bHistoryTableBroadcastTarget || !pThis->pFruitConfiguration->bUseSharedMemoryHistoryTable)
      else
      {

// kh 20.02.07 a) skip transmit to processors sharing another history table which have not 
// the bHistoryTableTarget property (i.e. they have not a history table master property for their own node) 

// kh 20.02.07 b) skip transmit to a processor which shares the history table

      } // if(pProcessorHandler->bHistoryTableBroadcastTarget || !pThis->pFruitConfiguration->bUseSharedMemoryHistoryTable)
    } // !if(i == pThis->nRank)

    i++;
  } // while((i < pThis->nSize) && !bBreak)

  pThis->pHistoryTableBroadcastRequestBuffer->bPreventDestruct = FALSE;

// kh 20.07.07 assertion does not hold any longer, if the history table is shared on nodes with the same name
//ASSERT((pThis->pHistoryTableBroadcastRequestBuffer->nReferenceCount > 0) || (pThis->nSize == 1));
  
  if(pThis->pHistoryTableBroadcastRequestBuffer->nReferenceCount > 0)
  {
  }
  else
  {
    Request_Destruct(pThis->pHistoryTableBroadcastRequestBuffer); // kh 20.02.07 nobody does it otherwise...
  }

  pThis->pHistoryTableBroadcastRequestBuffer = NULL; // kh 20.02.07 prepare next reinitialization

  nResult = nResultTmp;

  return nResult;
}

int YBWCManager_BroadcastHistTotTable(YBWCManager* pThis)
{
  int               nResult;
  int               nResultTmp;

  int               i;
  BOOL              bBreak;

  ProcessorHandler* pProcessorHandler;
  Request*          pRequest;

  nResult     = MPI_SUCCESS;
  nResultTmp  = MPI_SUCCESS;

  ASSERT(!pThis->pHistTotTableBroadcastRequestBuffer);

  if(pThis->pHistTotTableBroadcastRequestBuffer == NULL)
  {
    pThis->pHistTotTableBroadcastRequestBuffer = Request_Construct((Request*)malloc(sizeof(Request)));
    nResult = Request_InitHistTotTableBroadcastBuffer(pThis->pHistTotTableBroadcastRequestBuffer);
    if(nResult == MPI_SUCCESS)
    {
      for(i = 0; i < HistorySize; i++) 
      {
        pThis->HistHitTableBuffer[i] = 0;
        pThis->HistTotTableBuffer[i] = 0;
      }

      pThis->nHistTotUpdateCount = 0;
    }
    else
    {
      if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
      {
        YBWCManager_Printf(pThis, "ERROR YBWCManager_BroadcastHistTotTable(... failed at Request_InitHistTotTableBroadcastBuffer(..., errorcode = %d\n", nResult);
      }
    }
  } // if(pThis->pHistTotTableBroadcastRequestBuffer == NULL)

  ASSERT(pThis->pHistTotTableBroadcastRequestBuffer);
  ASSERT(pThis->pHistTotTableBroadcastRequestBuffer->nReferenceCount == 0);

  pThis->pHistTotTableBroadcastRequestBuffer->bPreventDestruct = TRUE;

  i       = 0; // kh 22.02.07 do not ignore RootMasterId 0
  bBreak  = FALSE;
  while((i < pThis->nSize) && !bBreak)
  {
    if(i == pThis->nRank)
    {
      // kh 22.02.07 skip
    } // if(i == pThis->nRank)
    else
    {
      pProcessorHandler = pThis->processorHandlerPool[i];
      if(pProcessorHandler->bHistoryTableBroadcastTarget || !pThis->pFruitConfiguration->bUseSharedMemoryHistoryTable)
      {
        if(pProcessorHandler->nBufferedRequestCount < 1 || true) // kh 22.02.07 do not limit the bandwidth at the moment
        {

// kh 22.02.07 pHistTotTableBroadcastRequestBuffer->nReferenceCount is potentially already decremented here
// via the cleanup for completed sends
// to prevent the deletion of pBroadcastRequestBuffer when reaching eventually a reference count of 0 in between
// a lock flag is used
          pRequest          = ProcessorHandler_CreateRequest(pProcessorHandler);

// kh 22.02.07 pHistTotTableBroadcastRequestBuffer->nReferenceCount is incremented here
          nResult           = Request_InitHistTotTableReplication(pRequest, pThis->pHistTotTableBroadcastRequestBuffer); 

          if(nResult == MPI_SUCCESS)
          {
            nResult = Request_SendBroadcastBuffer(pRequest);

            if(nResult == MPI_SUCCESS)
            {
            }
            else
            {
              if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
              {
                YBWCManager_Printf(pThis, "ERROR YBWCManager_BroadcastHistTotTable(... failed at Request_SendBroadcastBuffer(..., errorcode = %d\n", nResult);
              }

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

// kh 22.02.07 defensive 
//            bBreak = TRUE;  
            }
          } // if(nResult == MPI_SUCCESS)
          else
          {
            if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
            {
              YBWCManager_Printf(pThis, "ERROR YBWCManager_BroadcastHistTotTable(... failed at Request_InitHashTableReplication(..., errorcode = %d\n", nResult);
            }

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

// kh 22.02.07 defensive
//          bBreak = TRUE; 
          } // !if(nResult == MPI_SUCCESS)
        } // if(pProcessorHandler->nBufferedRequestCount < 1 || true)
        else
        {
          if(pThis->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_INFO_PRIO_2)
          {
            YBWCManager_Printf(pThis, 
                               "YBWCManager_BroadcastHistTotTable(... nBufferedRequestCount for ProcessorHandler <%d> is still %d, send is suppressed\n",
                               pProcessorHandler->nId,
                               pProcessorHandler->nBufferedRequestCount);
          }
        } // !if(pProcessorHandler->nBufferedRequestCount < 1 || true)
      } // if(pProcessorHandler->bHistoryTableBroadcastTarget || !pThis->pFruitConfiguration->bUseSharedMemoryHistoryTable)
      else
      {

// kh 22.02.07 a) skip transmit to processors sharing another history table which have not 
// the bHistoryTableTarget property (i.e. they have not a history table master property for their own node) 

// kh 22.02.07 b) skip transmit to a processor which shares the history table

      } // if(pProcessorHandler->bHistoryTableBroadcastTarget || !pThis->pFruitConfiguration->bUseSharedMemoryHistoryTable)
    } // !if(i == pThis->nRank)

    i++;
  } // while((i < pThis->nSize) && !bBreak)

  pThis->pHistTotTableBroadcastRequestBuffer->bPreventDestruct = FALSE;

// kh 22.07.07 assertion does not hold any longer, if the history table is shared on nodes with the same name
//ASSERT((pThis->pHist>TotTableBroadcastRequestBuffer->nReferenceCount > 0) || (pThis->nSize == 1));
  
  if(pThis->pHistTotTableBroadcastRequestBuffer->nReferenceCount > 0)
  {
  }
  else
  {
    Request_Destruct(pThis->pHistTotTableBroadcastRequestBuffer); // kh 22.02.07 nobody does it otherwise...
  }

  pThis->pHistTotTableBroadcastRequestBuffer = NULL; // kh 22.02.07 prepare next reinitialization

  nResult = nResultTmp;

  return nResult;
}
