#include "RequestDispatcher.h"

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

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

#include "protocol.h"
#include "trans.h"
#include "sort.h"

RequestDispatcher* RequestDispatcher_Construct(RequestDispatcher* pThis)
{
  pThis->nDummy = 4711;

  return pThis;
}

void RequestDispatcher_Destruct(RequestDispatcher* pThis)
{
  if(pThis)
  {
    free(pThis);
  }
}

int RequestDispatcher_Dispatch(RequestDispatcher* pThis, Request* pRequest)
{
  int               nResult;

  ProcessorHandler* pProcessorHandler;
  Result*           pResult;

  nResult = MPI_SUCCESS;

  if(pRequest->bDispatchedFirst)
  {
    nResult = Request_GetParameterFromBuffer(pRequest);
    pRequest->bDispatchedFirst = FALSE;
  }

  if(nResult == MPI_SUCCESS)
  {
    switch(pRequest->nType)
    {
    case REQUEST_TYPE_UNDEFINED:
      nResult = MPI_ERR_OTHER;
      if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
      {
        YBWCManager_Printf(g_pYBWCManagerInstance, "ERROR RequestDispatcher_Dispatch(... failed at switch(pRequest->nType) (REQUEST_TYPE_UNDEFINED), errorcode = %d\n", nResult);
      }

      break;

    case REQUEST_TYPE_ROOT_MASTER_LOGON_INVITATION:
      ASSERT(!g_pYBWCManagerInstance->bRootMaster);
      ASSERT(pRequest->nSourceId == 0);

// kh 06.09.06 "out of sync" problems are exceptionally not expected during startup, 
// so the assertion should hold
      ASSERT(g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_IDLE);

      g_pYBWCManagerInstance->bLoggedOn = TRUE;

      pProcessorHandler = g_pYBWCManagerInstance->processorHandlerPool[pRequest->nSourceId];
      pResult           = ProcessorHandler_CreateResult(pProcessorHandler);
      nResult           = Result_InitNonRootMasterLogon(pResult);

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

    case REQUEST_TYPE_ROOT_MASTER_LOGOFF_INVITATION:
      ASSERT(!g_pYBWCManagerInstance->bRootMaster);
      ASSERT(pRequest->nSourceId == 0);
      ASSERT(g_pYBWCManagerInstance->bLoggedOn);

// kh 13.09.06 "out of sync" problems are quite possible
      ASSERT(    !pRequest->bDelayedDispatch 
              || (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_IDLE)
            /*|| (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_SUPPORT_SEARCH)*/);

      if(    (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_IDLE)
          || (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_SUPPORT_SEARCH))
      {

// kh 19.09.06 defensive, a logoff invitation will only be dispatched in idle mode
        ASSERT(!g_pYBWCManagerInstance->bStoppingActive);
        g_pYBWCManagerInstance->nState = YBWC_MANAGER_STATE_IDLE; 

// kh 07.02.08 make sure all requests sent have been processed (e.g. broadcasted hash table entries to other processors)
        YBWCManager_WaitForSyncAfterBroadcast(g_pYBWCManagerInstance, YBWC_MANAGER_SYNC_AFTER_BROADCAST_TIMEOUT);

        g_pYBWCManagerInstance->bLoggedOn = FALSE;

        YBWCManager_DetachSharedMemAll(g_pYBWCManagerInstance);

// kh 19.09.06 a three way handshake is necessary for a proper shutdown
// step 1: root master invitates for logoff
// step 2: root master waits until all non root master have send the log off acknowledge result (see below)
//         important: all processors have to service messages further on (but of course no new requests 
//                    for work will be generated after a processor has handled his logoff invitation)
// step 3: root master requests all non root master to shutdown
//      g_pYBWCManagerInstance->nState    = YBWC_MANAGER_STATE_SHUTDOWN;

        pProcessorHandler = g_pYBWCManagerInstance->processorHandlerPool[pRequest->nSourceId];
        pResult           = ProcessorHandler_CreateResult(pProcessorHandler);
        nResult           = Result_InitNonRootMasterLogoff(pResult);

        if(nResult == MPI_SUCCESS)
        {
          nResult = Result_Send(pResult);
          if(nResult == MPI_SUCCESS)
          {
          }
          else
          {
            if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
            {
              YBWCManager_Printf(g_pYBWCManagerInstance, "ERROR RequestDispatcher_Dispatch(... failed at Result_Send(..., errorcode = %d\n", nResult);
            }
          }
        }
        else
        {
          if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
          {
            YBWCManager_Printf(g_pYBWCManagerInstance, "ERROR RequestDispatcher_Dispatch(... failed at Result_InitNonRootMasterLogoff(..., errorcode = %d\n", nResult);
          }
        }
      }
      else
      {
        ASSERT(    (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_SEARCHING)
                || (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_REQUEST_FOR_WORK_SEND));

        YBWCManager_BufferRequestForDelayedDispatch(g_pYBWCManagerInstance, pRequest);
      }

      break;

    case REQUEST_TYPE_ROOT_MASTER_SHUTDOWN:
      ASSERT(!g_pYBWCManagerInstance->bRootMaster);
      ASSERT(pRequest->nSourceId == 0);

// kh 13.10.06 if the root master exits with a fatal error this assertion may not hold, 
// because the non root master are not shutdown with the full three way handshake protocol
      ASSERT(!g_pYBWCManagerInstance->bLoggedOn);  

// kh 13.09.06 "out of sync" problems are quite possible
      ASSERT(    !pRequest->bDelayedDispatch 
              || (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_IDLE)
            /*|| (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_SUPPORT_SEARCH)*/);

      if(    (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_IDLE)
          || (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_SUPPORT_SEARCH))
      {

// kh 19.09.06 defensive, a request for shutdown will only be dispatched in idle mode
        ASSERT(!g_pYBWCManagerInstance->bStoppingActive);
        g_pYBWCManagerInstance->nState = YBWC_MANAGER_STATE_IDLE; 

        g_pYBWCManagerInstance->bLoggedOn = FALSE; // kh 20.09.06 defensive, already logged off is expected

// kh 19.09.06 a three way handshake is necessary for a proper shutdown 
// (see also comment from 19.09.06 above for case REQUEST_TYPE_ROOT_MASTER_LOGOFF_INVITATION)
// here step 3: root master requests all non root master to shutdown is handled
        g_pYBWCManagerInstance->nState    = YBWC_MANAGER_STATE_SHUTDOWN;

        pProcessorHandler = g_pYBWCManagerInstance->processorHandlerPool[pRequest->nSourceId];
        pResult           = ProcessorHandler_CreateResult(pProcessorHandler);
        nResult           = Result_InitNonRootMasterShutdown(pResult);

        if(nResult == MPI_SUCCESS)
        {
          nResult = Result_Send(pResult);
          if(nResult == MPI_SUCCESS)
          {
          }
          else
          {
            if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
            {
              YBWCManager_Printf(g_pYBWCManagerInstance, "ERROR RequestDispatcher_Dispatch(... failed at Result_Send(..., errorcode = %d\n", nResult);
            }
          }
        }
        else
        {
          if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
          {
            YBWCManager_Printf(g_pYBWCManagerInstance, "ERROR RequestDispatcher_Dispatch(... failed at Result_InitNonRootMasterLogoff(..., errorcode = %d\n", nResult);
          }
        }
      }
      else
      {
        ASSERT(    (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_SEARCHING)
                || (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_REQUEST_FOR_WORK_SEND));

        YBWCManager_BufferRequestForDelayedDispatch(g_pYBWCManagerInstance, pRequest);
      }

      break;

    case REQUEST_TYPE_ROOT_MASTER_IDLE_INVITATION:
      ASSERT(!g_pYBWCManagerInstance->bRootMaster);
      ASSERT(pRequest->nSourceId == 0);
      ASSERT(g_pYBWCManagerInstance->bLoggedOn);

// kh 20.09.06 "out of sync" problems are quite possible
      ASSERT(    !pRequest->bDelayedDispatch 
              || (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_IDLE)
              || (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_SUPPORT_SEARCH));

      if(    (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_IDLE)
          || (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_SUPPORT_SEARCH))
      {
        g_pYBWCManagerInstance->nState = YBWC_MANAGER_STATE_IDLE; 
      }
      else
      {
        ASSERT(    (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_SEARCHING)
                || (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_REQUEST_FOR_WORK_SEND));

        YBWCManager_BufferRequestForDelayedDispatch(g_pYBWCManagerInstance, pRequest);
      }

      break;

    case REQUEST_TYPE_ROOT_MASTER_SYNC_POSITION:
      ASSERT(!g_pYBWCManagerInstance->bRootMaster);
      ASSERT(pRequest->nSourceId == 0);
      ASSERT(g_pYBWCManagerInstance->bLoggedOn);

// kh 13.09.06 "out of sync" problems are quite possible
      ASSERT(    !pRequest->bDelayedDispatch 
              || (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_IDLE)
              || (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_SUPPORT_SEARCH));

      if(    (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_IDLE)
          || (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_SUPPORT_SEARCH))
      {
        g_pYBWCManagerInstance->nState          = YBWC_MANAGER_STATE_IDLE;

        g_pYBWCManagerInstance->nSyncPositionId = pRequest->nSyncPositionId;

        g_pYBWCManagerInstance->nTotalNodes = 0;

// kh 09.08.06 use Fruit functions
        fruit_actions_for_sync_position_received(pRequest->psSyncPosition);
      }
      else
      {
        ASSERT(    (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_SEARCHING)
                || (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_REQUEST_FOR_WORK_SEND));

        YBWCManager_BufferRequestForDelayedDispatch(g_pYBWCManagerInstance, pRequest);
      }

      break;

    case REQUEST_TYPE_ROOT_MASTER_SUPPORT_SEARCH:
      ASSERT(!g_pYBWCManagerInstance->bRootMaster);
      ASSERT(pRequest->nSourceId == 0);
      ASSERT(g_pYBWCManagerInstance->bLoggedOn);

// kh 13.09.06 "out of sync" problems are quite possible
      ASSERT(    !pRequest->bDelayedDispatch 
              || (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_IDLE)
              || (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_SUPPORT_SEARCH));

      if(    (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_IDLE) 
          || (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_SUPPORT_SEARCH))
      {
        g_pYBWCManagerInstance->nState                  = YBWC_MANAGER_STATE_SUPPORT_SEARCH;

// kh 27.09.06 send requests for work now initially fast (again) and 
// slow down in case nNoWorkAvailableInARow increments continuously (may be tuned with alternative ideas)
        g_pYBWCManagerInstance->nNoWorkAvailableInARow  = 0;

// kh 25.03.08 init here, actual trans date is transmitted with the job info
//      trans_set_date(Trans, 0);

// kh 05.06.08 hash table entries are tranmitted asynchronously, use last stable trans date 
// until actual trans date is transmitted with the job info
        trans_set_date(Trans, Trans->date);

// kh 04.04.08 favor "gross" node counting (see also comment from 04.04.08 for search_clear(... in search.cpp)
        SearchCurrent->node_nb  = 0;
        SearchCurrent->time     = 0.0;
        SearchCurrent->speed    = 0.0;
        SearchCurrent->cpu      = 0.0;

        if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_INFO_PRIO_2)
        {
          YBWCManager_Printf(g_pYBWCManagerInstance, "trans_set_date(... %d\n", Trans->date);
        }

      }
      else
      {
        ASSERT(    (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_SEARCHING)
                || (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_REQUEST_FOR_WORK_SEND));

        YBWCManager_BufferRequestForDelayedDispatch(g_pYBWCManagerInstance, pRequest);
      }
      break;

    case REQUEST_TYPE_ROOT_MASTER_STOP_REMOTE_SEARCH:
      ASSERT(!g_pYBWCManagerInstance->bRootMaster); // kh 12.09.06 the root master will never be stopped by anybody
      ASSERT(pRequest->nSourceId == 0);             
      ASSERT(g_pYBWCManagerInstance->bLoggedOn);

// kh 06.09.06 single caused "out of sync" problems are exceptionally not expected, 
// so the assertion should hold (but this non root master may have completed the remote search in between)
      ASSERT(    (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_SEARCHING)
              || (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_IDLE)); 

      if(g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_SEARCHING) // kh 06.09.06 defensive anyway
      {

// kh 05.09.06 use Fruit functions
        fruit_actions_for_stop_remote_received();
      }
      break;

    case REQUEST_TYPE_ROOT_MASTER_NEW_GAME:
      ASSERT(!g_pYBWCManagerInstance->bRootMaster);
      ASSERT(pRequest->nSourceId == 0);
      ASSERT(g_pYBWCManagerInstance->bLoggedOn);

// kh 13.09.06 "out of sync" problems are quite possible
      ASSERT(    !pRequest->bDelayedDispatch 
              || (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_IDLE)
              || (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_SUPPORT_SEARCH));

      if(    (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_IDLE)
          || (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_SUPPORT_SEARCH))
      {

        g_pYBWCManagerInstance->nState = YBWC_MANAGER_STATE_IDLE;

// kh 09.08.06 use Fruit functions
        fruit_actions_for_new_game_received();

// kh 05.01.07 sync root master and non root master after uci new game 
// at the moment used for a synchronized transposition table clear, to avoid an asynchronous  
// transposition table clear by the non root master in fruit_actions_for_new_game_received(... (see above) 
// while the root master (or non root master) may already have filled the table with some information
        pProcessorHandler = g_pYBWCManagerInstance->processorHandlerPool[pRequest->nSourceId];
        pResult           = ProcessorHandler_CreateResult(pProcessorHandler);
        nResult           = Result_InitNonRootMasterSyncNewGame(pResult);

        if(nResult == MPI_SUCCESS)
        {
          nResult = Result_Send(pResult);
          if(nResult == MPI_SUCCESS)
          {
          }
          else
          {
            if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
            {
              YBWCManager_Printf(g_pYBWCManagerInstance, "ERROR RequestDispatcher_Dispatch(... failed at Result_Send(..., errorcode = %d\n", nResult);
            }
          }
        }
        else
        {
          if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
          {
            YBWCManager_Printf(g_pYBWCManagerInstance, "ERROR RequestDispatcher_Dispatch(... failed at Result_InitNonRootMasterSyncNewGame(..., errorcode = %d\n", nResult);
          }
        }
      }
      else
      {
        ASSERT(    (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_SEARCHING)
                || (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_REQUEST_FOR_WORK_SEND));

        YBWCManager_BufferRequestForDelayedDispatch(g_pYBWCManagerInstance, pRequest);
      }
      break;

    case REQUEST_TYPE_ROOT_MASTER_SET_OPTION:
      ASSERT(!g_pYBWCManagerInstance->bRootMaster);
      ASSERT(pRequest->nSourceId == 0);
      ASSERT(g_pYBWCManagerInstance->bLoggedOn);

// kh 07.02.08 "out of sync" problems are quite possible
      ASSERT(    !pRequest->bDelayedDispatch 
              || (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_IDLE)
              || (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_SUPPORT_SEARCH));

      if(    (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_IDLE)
          || (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_SUPPORT_SEARCH))
      {

//      g_pYBWCManagerInstance->nState = YBWC_MANAGER_STATE_IDLE;

// kh 07.02.08 use Fruit functions
        fruit_actions_for_set_option_received(pRequest->psOptionName, pRequest->psOptionValue);

// kh 07.02.08 sync root master and non root master after uci set option 
// at the moment used for a synchronized transposition table resize and clear
        pProcessorHandler = g_pYBWCManagerInstance->processorHandlerPool[pRequest->nSourceId];
        pResult           = ProcessorHandler_CreateResult(pProcessorHandler);
        nResult           = Result_InitNonRootMasterSyncSetOption(pResult);

        if(nResult == MPI_SUCCESS)
        {
          nResult = Result_Send(pResult);
          if(nResult == MPI_SUCCESS)
          {
          }
          else
          {
            if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
            {
              YBWCManager_Printf(g_pYBWCManagerInstance, "ERROR RequestDispatcher_Dispatch(... failed at Result_Send(..., errorcode = %d\n", nResult);
            }
          }
        }
        else
        {
          if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
          {
            YBWCManager_Printf(g_pYBWCManagerInstance, "ERROR RequestDispatcher_Dispatch(... failed at Result_InitNonRootMasterSyncNewGame(..., errorcode = %d\n", nResult);
          }
        }
      }
      else
      {
        ASSERT(    (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_SEARCHING)
                || (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_REQUEST_FOR_WORK_SEND));

        YBWCManager_BufferRequestForDelayedDispatch(g_pYBWCManagerInstance, pRequest);
      }
      break;

    case REQUEST_TYPE_ROOT_MASTER_REMOTE_TEST:
      ASSERT(!g_pYBWCManagerInstance->bRootMaster);
      ASSERT(pRequest->nSourceId == 0);
      ASSERT(g_pYBWCManagerInstance->bLoggedOn);

// kh 13.09.06 "out of sync" problems are quite possible
      ASSERT(    !pRequest->bDelayedDispatch 
              || (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_IDLE)
              || (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_SUPPORT_SEARCH));

      if(    (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_IDLE)
          || (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_SUPPORT_SEARCH))
      {

// kh 12.09.06 for future expansions: set a special remote searching flag here for the non root master

// kh 10.08.06 use Fruit functions
        fruit_actions_for_remote_test_received(pRequest->psGoCommands);
      }
      else
      {
        ASSERT(    (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_SEARCHING)
                || (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_REQUEST_FOR_WORK_SEND));

        YBWCManager_BufferRequestForDelayedDispatch(g_pYBWCManagerInstance, pRequest);
      }
      break;

    case REQUEST_TYPE_ROOT_MASTER_MACHINE_INFO:
      ASSERT(!g_pYBWCManagerInstance->bRootMaster);
      ASSERT(pRequest->nSourceId == 0);
      ASSERT(g_pYBWCManagerInstance->bLoggedOn);

// kh 13.12.06 "out of sync" problems are exceptionally not expected during startup, 
// so the assertion should hold
      ASSERT(g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_IDLE);

      YBWCManager_SetMachineInfo(g_pYBWCManagerInstance);

      YBWCManager_AdjustProcessPriority(g_pYBWCManagerInstance);

// the g_pYBWCManagerInstance->bHashTableMaster property is known now and could be used
// At the moment it is not used (the first process on a node "wins" an creates the shared memory table)
      trans_alloc(Trans);

      history_alloc(&gpHistory); // kh 08.02.07

      break;

    case REQUEST_TYPE_NON_ROOT_MASTER_SYNC_AFTER_BROADCAST:
      ASSERT(pRequest->nSourceId != 0);                             // kh 07.02.08 the root master syncs implicit
      ASSERT(pRequest->nSourceId != g_pYBWCManagerInstance->nRank); // kh 07.02.08 a non root master will never try to get work from himself

      pProcessorHandler = g_pYBWCManagerInstance->processorHandlerPool[pRequest->nSourceId];
      pResult           = ProcessorHandler_CreateResult(pProcessorHandler);
      nResult           = Result_InitSyncAfterBroadcast(pResult);

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

    case REQUEST_TYPE_SLAVE_TRY_TO_GET_WORK:
      ASSERT(pRequest->nSourceId != 0);                             // kh 06.09.06 the root master is never a slave and will never ask for work 
      ASSERT(pRequest->nSourceId != g_pYBWCManagerInstance->nRank); // kh 06.09.06 a slave will never try to get work from himself

// kh 19.09.06 this potential master may have already handled a logoff invitation and is no longer logged on
//    ASSERT(g_pYBWCManagerInstance->bLoggedOn);

// kh 12.09.06 for future expansions: test the special remote searching flag here (see above)
// and suppress (configurable) the further distribution of subwork

      YBWCManager_CheckSendWorkToSlave(g_pYBWCManagerInstance, 
                                       pRequest->nSourceId, 
                                       pRequest->nSyncPositionId);
      break;

    case REQUEST_TYPE_MASTER_STOP:
      ASSERT(!g_pYBWCManagerInstance->bRootMaster); // kh 12.09.06 the root master will never be stopped by anybody

// kh 27.10.06 will hold, if only the root master distributes work
      ASSERT(    (pRequest->nSourceId == 0) 
              || !g_pYBWCManagerInstance->pFruitConfiguration->bOnlyDistributeWorkOfRootMaster); 

      ASSERT(g_pYBWCManagerInstance->bLoggedOn);

// kh 13.10.06 "out of sync" problems are quite possible
// the non root master may have completed the search (and even some more) in between

// kh 13.10.06 stoppping is only meaningful, if the access key for the subproblem (master id and work id) 
// is correct (i.e. the non root master is still searching for the subpoblem the master wants to stop)

// kh 13.10.06 any state is possible (e.g. the non root master may have even switched from 
// YBWC_MANAGER_STATE_SUPPORT_SEARCH to YBWC_MANAGER_STATE_IDLE) triggered by the next 
// REQUEST_TYPE_ROOT_MASTER_SYNC_POSITION of the root master
/*
      ASSERT(    (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_SEARCHING)
              || (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_IDLE));
*/

      if(g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_SEARCHING)
      {

// kh 13.10.06 non root master could search already for REQUEST_TYPE_ROOT_MASTER_REMOTE_TEST
//      ASSERT(g_pYBWCManagerInstance->bSearchingSubproblem); 

        if(g_pYBWCManagerInstance->bSearchingSubproblem)
        {
          if(g_pYBWCManagerInstance->nMasterId == pRequest->nSourceId)
          {
            if(g_pYBWCManagerInstance->pWorkAvailableResult->nWorkId == pRequest->nWorkId)
            {

// kh 21.03.07 for debug purposes only
              g_pYBWCManagerInstance->bRealStopReceived       = TRUE; 
              g_pYBWCManagerInstance->nNodesSinceStopReceive  = SearchCurrent->node_local_nb;

// kh 07.12.06 g_pYBWCManagerInstance->bStoppingActive may be set already by a window update research request
// and not yet handled (was observed with many processors (e.g. 15) and for the relatively slow debug version of fruit)
              if(g_pYBWCManagerInstance->bStoppingActive)
              {
                ASSERT(g_pYBWCManagerInstance->bRerunSearch);

                if(g_pYBWCManagerInstance->bRerunSearch)
                {
                }
                else
                {
                  if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
                  {
                    YBWCManager_Printf(g_pYBWCManagerInstance, 
                                       "ERROR stop from master <%d> received, window update rerun to cancel not set\n",
                                       pRequest->nSourceId);
                  }
                }

                g_pYBWCManagerInstance->bRerunSearch = FALSE; // kh 20.12.06 cancel any window update rerun

                if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_WARNING_PRIO_1)
                {
                  YBWCManager_Printf(g_pYBWCManagerInstance, 
                                     "INFO stop from master <%d> received, window update rerun is cancelled \n",
                                     pRequest->nSourceId);
                }

// kh 07.12.06 possible in rare cases, if a former update search window request was dispatched
// while the actual search is still stopping by this request
                if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_WARNING_PRIO_1)
                {
                  YBWCManager_Printf(g_pYBWCManagerInstance, 
                                     "INFO stop from master <%d> received and slave is searching for that master, and nWorkId to stop = " F12INT64d " == actual nWorkId = " F12INT64d " but worker is already and still stopping for a research\n",
                                     pRequest->nSourceId,
                                     pRequest->nWorkId,
                                     g_pYBWCManagerInstance->pWorkAvailableResult->nWorkId);
                }
              } // if(g_pYBWCManagerInstance->bStoppingActive)
              else
              {

// kh 19.09.06 use Fruit functions
                g_pYBWCManagerInstance->nTotalWorkAbortedCount++;
                fruit_actions_for_stop_received();

              } // !if(g_pYBWCManagerInstance->bStoppingActive)
            }
            else
            {
              if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_INFO_PRIO_1)
              {
                YBWCManager_Printf(g_pYBWCManagerInstance, 
                                   "INFO stop from master <%d> received and slave is searching for that master, but nWorkId to stop = " F12INT64d " and actual nWorkId = " F12INT64d "\n",
                                   pRequest->nSourceId,
                                   pRequest->nWorkId,
                                   g_pYBWCManagerInstance->pWorkAvailableResult->nWorkId);
              }
            }
          }
          else
          {
            if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_INFO_PRIO_1)
            {
              YBWCManager_Printf(g_pYBWCManagerInstance, 
                                 "INFO stop from master <%d> and for nWorkId to stop = " F12INT64d " received but slave is searching already for master <%d>\n",
                                 pRequest->nSourceId,
                                 pRequest->nWorkId,
                                 g_pYBWCManagerInstance->nMasterId);
            }
          }
        }
        else
        {
          if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_WARNING_PRIO_1)
          {
            YBWCManager_Printf(g_pYBWCManagerInstance, 
                               "WARNING stop from master <%d> and for nWorkId to stop = " F12INT64d " received and slave is searching, but slave is not searching for a subproblem\n",
                               pRequest->nSourceId,
                               pRequest->nWorkId);
          }
        }
      }
      else
      {
        if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_INFO_PRIO_1)
        {
          YBWCManager_Printf(g_pYBWCManagerInstance, 
                             "INFO stop from master <%d> and for nWorkId to stop = " F12INT64d " received, but slave has finished the search in between\n",
                             pRequest->nSourceId,
                             pRequest->nWorkId);
        }
      }

      break;

    case REQUEST_TYPE_SLAVE_PROCESS_SEARCH_RESULT:
      ASSERT(pRequest->nSourceId != 0);                             // kh 11.10.06 the root master is never a slave and will never send search result for a subproblem
      ASSERT(pRequest->nSourceId != g_pYBWCManagerInstance->nRank); // kh 11.10.06 a slave will never receive a search result for a subproblem from himself

// 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;
    
// kh 06.09.06 the master may have completed the search in between
      if(g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_SEARCHING)
      {
        YBWCManager_ProcessSlaveResult(g_pYBWCManagerInstance, pRequest);
      }
      break;

    case REQUEST_TYPE_MASTER_UPDATE_SEARCH_WINDOW:
      ASSERT(!g_pYBWCManagerInstance->bRootMaster); // kh 12.09.06 the root master search window will never be updated by anybody

// kh 27.10.06 will hold, if only the root master distributes work
      ASSERT((pRequest->nSourceId == 0) || !g_pYBWCManagerInstance->pFruitConfiguration->bOnlyDistributeWorkOfRootMaster); 
      ASSERT(pRequest->nSourceId != g_pYBWCManagerInstance->nRank); // kh 23.03.07 a slave will never receive an update search window request from himself

      if(pRequest->nSourceId == g_pYBWCManagerInstance->nRank)
      {
        if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
        {
          YBWCManager_Printf(g_pYBWCManagerInstance, 
                             "ERROR RequestDispatcher_Dispatch(... failed self window update from source %d for rank %d received\n",
                             pRequest->nSourceId,
                             g_pYBWCManagerInstance->nRank);
        }
      }

      ASSERT(g_pYBWCManagerInstance->bLoggedOn);

// kh 13.10.06 "out of sync" problems are quite possible
// the non root master may have completed the search (and even some more) in between

// kh 13.10.06 updating the search window is only meaningful, if the access key for the subproblem (master id and work id) 
// is correct (i.e. the non root master is still searching for the subpoblem the master wants to 
// update the search window for)

// kh 13.10.06 any state is possible (e.g. the non root master may have even switched from 
// YBWC_MANAGER_STATE_SUPPORT_SEARCH to YBWC_MANAGER_STATE_IDLE) triggered by the next 
// REQUEST_TYPE_ROOT_MASTER_SYNC_POSITION of the root master
/*
      ASSERT(    (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_SEARCHING)
              || (g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_IDLE));
*/

      if(g_pYBWCManagerInstance->nState == YBWC_MANAGER_STATE_SEARCHING)
      {

// kh 13.10.06 non root master could search already for REQUEST_TYPE_ROOT_MASTER_REMOTE_TEST
//      ASSERT(g_pYBWCManagerInstance->bSearchingSubproblem); 

        if(g_pYBWCManagerInstance->bSearchingSubproblem)
        {
          if(g_pYBWCManagerInstance->nMasterId == pRequest->nSourceId)
          {
            if(g_pYBWCManagerInstance->pWorkAvailableResult->nWorkId == pRequest->nWorkId)
            {

// kh 19.09.06 use Fruit functions
              fruit_actions_for_update_search_window_received(pRequest->nAlpha, pRequest->nBeta);
            }
            else
            {
              if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_INFO_PRIO_1)
              {
                YBWCManager_Printf(g_pYBWCManagerInstance, 
                                   "INFO update search window from master <%d> received and slave is searching for that master, but nWorkId to update the search window for = " F12INT64d " and actual nWorkId = " F12INT64d "\n",
                                   pRequest->nSourceId,
                                   pRequest->nWorkId,
                                   g_pYBWCManagerInstance->pWorkAvailableResult->nWorkId);
              }
            }
          }
          else
          {
            if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_INFO_PRIO_1)
            {
              YBWCManager_Printf(g_pYBWCManagerInstance, 
                                 "INFO update the search window from master <%d> and for nWorkId to update the search window for = " F12INT64d " received but slave is searching already for master <%d>\n",
                                 pRequest->nSourceId,
                                 pRequest->nWorkId,
                                 g_pYBWCManagerInstance->nMasterId);
            }
          }
        }
        else
        {
          if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_WARNING_PRIO_1)
          {
            YBWCManager_Printf(g_pYBWCManagerInstance, 
                               "WARNING update the search window from master <%d> and for nWorkId to update the search window for = " F12INT64d " received and slave is searching, but slave is not searching for a subproblem\n",
                               pRequest->nSourceId,
                               pRequest->nWorkId);
          }
        }
      }
      else
      {
        if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_INFO_PRIO_1)
        {
          YBWCManager_Printf(g_pYBWCManagerInstance, 
                             "INFO update the search window from master <%d> and for nWorkId to update the search window for = " F12INT64d " received, but slave has finished the search in between\n",
                             pRequest->nSourceId,
                             pRequest->nWorkId);
        }
      }

      break;

    case REQUEST_TYPE_HASH_TABLE_REPLICATION:
      ASSERT(pRequest->nSourceId != g_pYBWCManagerInstance->nRank); // kh 15.11.06 a processor will never receive replicated entries by himself 

// kh 07.12.06 assertion was observed during (fast) finalizing environment via quit (e.g. in auto tester mode)
//    ASSERT(g_pYBWCManagerInstance->bLoggedOn); 

// kh 15.11.06 hash table updates from other processors are handled at any time

// kh 15.11.06 use Fruit functions
//    fruit_actions_for_hash_table_replication_received(pRequest);

      ASSERT(pRequest->pHashTableBuffer);
      ASSERT(pRequest->pHashTableBuffer == g_pYBWCManagerInstance->pHashTableReceiveBuffer); // kh 15.11.06 was set when getting the parameters

// kh 07.12.06 this was already done directly when getting the parameters for a better performance
/*
      HashTableBuffer_FlushToTranspositionTable(pRequest->pHashTableBuffer, Trans);
*/

      break;

    case REQUEST_TYPE_HASH_TABLE_BROADCAST_BUFFER:
      ASSERT(false); // kh 06.12.06 this request will never be received/dispatched, it is only used as a broadcast buffer 
      break;
      
    case REQUEST_TYPE_HISTORY_TABLE_REPLICATION:
      ASSERT(pRequest->nSourceId != g_pYBWCManagerInstance->nRank); // kh 20.02.07 a processor will never receive replicated entries by himself 

// kh 07.12.06 assertion was observed during (fast) finalizing environment via quit (e.g. in auto tester mode)
//    ASSERT(g_pYBWCManagerInstance->bLoggedOn); 

// kh 20.02.07 history table updates from other processors are handled at any time

// kh 20.02.07 use Fruit functions
//    fruit_actions_for_history_table_replication_received(pRequest);

// kh 20.02.07 any dispatching was already done directly when getting the parameters for a better performance

      break;

    case REQUEST_TYPE_HISTORY_TABLE_BROADCAST_BUFFER:
      ASSERT(false); // kh 20.02.07 this request will never be received/dispatched, it is only used as a broadcast buffer 
      break;
      
    case REQUEST_TYPE_HIST_TOT_TABLE_REPLICATION:
      ASSERT(pRequest->nSourceId != g_pYBWCManagerInstance->nRank); // kh 22.02.07 a processor will never receive replicated entries by himself 

// kh 07.12.06 assertion was observed during (fast) finalizing environment via quit (e.g. in auto tester mode)
//    ASSERT(g_pYBWCManagerInstance->bLoggedOn); 

// kh 22.02.07 histtot / histhit table updates from other processors are handled at any time

// kh 22.02.07 use Fruit functions
//    fruit_actions_for_histtot_table_replication_received(pRequest);

// kh 22.02.07 any dispatching was already done directly when getting the parameters for a better performance

      break;

    case REQUEST_TYPE_HIST_TOT_TABLE_BROADCAST_BUFFER:
      ASSERT(false); // kh 22.02.07 this request will never be received/dispatched, it is only used as a broadcast buffer 
      break;
      
	  default:
      nResult = MPI_ERR_OTHER;
      if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
      {
        YBWCManager_Printf(g_pYBWCManagerInstance, "ERROR RequestDispatcher_Dispatch(... failed at switch(pRequest->nType) (default), errorcode = %d\n", nResult);
      }
		  break;
	  }
  }
  else
  {
    if(g_pYBWCManagerInstance->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
    {
      YBWCManager_Printf(g_pYBWCManagerInstance, "ERROR RequestDispatcher_Dispatch(... failed at Request_GetParamterFromBuffer(..., errorcode = %d\n", nResult);
    }
  }

  return nResult;
}
