/*
    NetPoolThread.c, Copyright  (c) by Boris Lutz,
    Swiss Federal Institute of Technology,
    Computer Engineering and Networks Laboratory.
 
    TOPSY -- A Teachable Operating System.
             Implementation of a tiny and simple
             micro kernel for teaching purposes.
 
    For further information, please visit http://www.tik.ee.ethz.ch/~topsy
 
    This software is provided under the terms of the GNU General Public 
    Licence. A full copy of the GNU GPL is provided in the file COPYING 
    found in the development root of Topsy.
*/
/*
	
    File:                  $Source: /home/ruf/cvs_Topsy/cvs/Topsy/Net/NetPoolThread.c,v $
    Author(s):             
    Affiliation:           ETH Zuerich, TIK
    Version:               $Revision: 2922 $
    Creation Date:         
    Last Date of Change:   $Date: 2007-03-19 17:48:52 +0100 (Mon, 19 Mär 2007) $      by: $Author: baderma $
 
*/


#include "Topsy.h"
#include "Support.h"
#include "Syscall.h"
#include "LWThreads.h"
#include "HashList.h"
#include "NetInQueueMngr.h"
#include "NetModulesNew.h"
#include "NetModulesDef.h"
#include "NetConfigMngr.h"
#include "NetPoolThread.h"
#include "Distributor.h"
#include "ModuleLoader.h"
#include "ModuleLookup.h"

void netPoolThreadMain(ThreadArg options)
{
  ThreadId			SenderTID;
  Message				ptMsg,
  stateMsg;
  LWPool				modulePool;
  HashList			lookupTable;
  Error				err;

  extern	ThreadId	netGInqThreadId;


  // Init
  lookupTable = hashListNew();
  if (lookupTable == NULL)
  {
    printf("PoolThread: Init failed (hashListNew)\n");
    tmExit();
  }
  // Init LWPool
  err = lwInit(&modulePool, NET_NUM_OF_LW);
  if (err != LW_OK)
  {
    printf("PoolThread: Init failed (lwInit)\n");
    tmExit();
  }
  // Allocate ModuleLoader
  err = lwCreate (modulePool, NET_MODULE_LOOKUP_THREAD,
                  netModuleLookupMain, lookupTable, NULL);
  if (err != LW_OK)
  {
    printf("PoolThread: Init failed (lwStart)\n");
    tmExit();
  }
  if ( hashListAdd(lookupTable,
                   (void*) NET_MODULE_LOOKUP_THREAD,
                   NET_MODULE_LOOKUP_ID) != HASHOK )
  {
    printf("PoolThread: Init failed (lwStart)\n");
    tmExit();
  }
  // Allocate ConversionTable Module (ModuleID => ThreadID)
  err = lwCreate (modulePool, NET_MODULE_LOADER_THREAD,
                  netModuleLoaderMain, lookupTable, NULL);
  if (err != LW_OK)
  {
    printf("PoolThread: Init failed (lwStart)\n");
    tmExit();
  }
  if ( hashListAdd(lookupTable,
                   (void*) NET_MODULE_LOADER_THREAD,
                   NET_MODULE_LOADER_ID) != HASHOK )
  {
    printf("PoolThread: Init failed (lwStart)\n");
    tmExit();
  }

  while (1)
  {
    // Wait for message from InQueueMngr
    SenderTID = ANY;
    err = tmMsgRecv (&SenderTID, ANYMSGTYPE, &ptMsg, INFINITY);
    printf(""); /* XXX this is a gcc hack */
    //printf("this is a gcc hack\n");
    if ( err != TM_MSGRECVOK)
    {
      //	printf("INQUEUE: after tmMsgRecv err = %i != %i\n",
      //			(int) err, (int)TM_MSGRECVOK);
      printf("PoolThread: MsgReceive failed\n");
      tmExit();
    }

    switch (ptMsg.id)
    {
      /* XXX not needed right now, may prove necessary later
       * needs to be completed if so and see NetInQueueMngr.c
       * "case NET_INQUEUE_PT_BUSY"
      case NET_CONFIG_REQUEST:
      	if (ptMsg.from != netGCfgThreadId) {	// Paranoia
      		printf("PoolThread: who the hell are you?!\n");
      		tmExit();
      	}
      	// Let the InQueueMngr know that I'm busy
      	stateMsg.id = NET_INQUEUE_PT_BUSY;
      	err = tmMsgSend (netGInqThreadId, &stateMsg);
      	if (err != TM_MSGSENDOK) {
      		printf("PoolThread: MsgSend failed\n");
      		tmExit();
      	}
      	// Process the config request

      	// XXX most important stuff is missing
      	
      	// Let the InQueueMngr know that I'm idle again
      	stateMsg.id = NET_INQUEUE_PT_IDLE;
      	err = tmMsgSend (netGInqThreadId, &stateMsg);
      	if (err != TM_MSGSENDOK) {
      		printf("PoolThread: MsgSend failed\n");
      		tmExit();
      	}
      	break;
      	*/
    case NET_QUEUE_DATA:
      if (ptMsg.from != netInqueueThread)
      {  /* Paranoia */
        printf("PoolThread: who the hell are you?!\n");
        tmExit();
      }
      /* Process the received message (InqMngr knows I'm busy
       * since it has sent me this queue message :) */
      /* just to be sure */
      netmodSend(modulePool,	NET_MODULE_IN_DISTRIBUTOR_ID,
                 ptMsg.msg.netqMsg.netData,
                 ptMsg.msg.netqMsg.netMeta);
      netmodRecv(modulePool, NULL, NULL);
      /* Let the InQueueMngr know that I'm idle again */
      stateMsg.id = NET_INQUEUE_PT_IDLE;
      err = tmMsgSend (netInqueueThread, &stateMsg);
      if (err != TM_MSGSENDOK)
      {
        printf("PoolThread: MsgSend failed\n");
        tmExit();
      }
      break;
    default:
      printf("PoolThread: unexpected message recieved\n");
    }
  }
}
