/*
    Copyright 2000 (c) by Claudio Jeker,
    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/Modules/ModuleLookup.c,v $
    Affiliation:           ETH Zuerich, TIK
    Version:               $Revision: 2922 $
    Last Date of Change:   $Date: 2007-03-19 17:48:52 +0100 (Mon, 19 Mär 2007) $  by: $Author: baderma $
 
*/
#include "ModuleLookup.h"
#include "NetModulesNew.h"
#include "NetModulesDef.h"
#include "NetDebug.h"
#include "NetAttr.h"
#include "LWThreads.h"
#include "HashList.h"
#include "Syscall.h"
#include "Support.h"

static ThreadId netModuleLookupException(LWPool lw, NetModuleId id);

void netModuleLookupInit(NetModule this)
{
  /* nothing has to be set */
  return;
}


int netModuleLookupConfig(NetModule this, Message *msg)
{
  /* nothing has to be set */
  return 0;
}


void netModuleLookupMain(LWPool lw, ThreadArg arg)
{
  HashList	lookupTable = (HashList) arg;
  ThreadId	from, to;
  Message		msg;


  while (1)
  {
    lwMsgRecv(lw, &from, 0, &msg, 0);
    if ((MessageId) msg.id != (MessageId) NET_QUEUE_DATA)
    {
      netdbgPrintf(0, "netModuleLookup: wrong message type (%i not %i) received\n",
                   msg.id, NET_QUEUE_DATA);
      continue;
    }
    hashListGet(lookupTable, (void **) &to, msg.msg.netqMsg.netId);
    /* if hashListGet fails to is set to 0 */
    if ( to == 0 )
    {
      netdbgPrintf(NETDEBUG_MODULES,
                   "netModuleLookup: module not yet loaded\n");
      to = netModuleLookupException(lw, msg.msg.netqMsg.netId);
      if ( to == 0 )
      {
        netmodRIP(lw, msg.msg.netqMsg.netData,
                  msg.msg.netqMsg.netMeta,
                  "netModuleLookup: temporary failed to load module\n");
        continue;
      }
    }
    if ( to == -1 )
    {
      netmodRIP(  lw, msg.msg.netqMsg.netData,
                  msg.msg.netqMsg.netMeta,
                  "netModuleLookup: permanently failed to find module\n");
      continue;
    }
    netdbgPrintf(NETDEBUG_MODULES,
                 "netModuleLookup: message from %i to %i (id %i)\n", (int) from,
                 (int) to, (int) msg.msg.netqMsg.netId);
    lwMsgSend(lw, to, &msg);
  }
}

static ThreadId netModuleLookupException(LWPool lw, NetModuleId id)
{
  Message msg;
  ThreadId loader = NET_MODULE_LOADER_THREAD;

  msg.id = NET_CONF_MODULEREQ;
  msg.msg.netConf.ModuleReq.request = id;
  if (lwMsgSend(lw, loader, &msg) != LW_OK)
  {
    netdbgPrintf(NETDEBUG_MODULES,
                 "netModuleLookupException: lwMsgSend failed\n");
    return 0;
  }

  if (lwMsgRecv(lw,  &loader, 0, &msg, 0) != TM_MSGSENDOK)
  {
    netdbgPrintf(NETDEBUG_MODULES,
                 "netModuleLookupException: lwMsgRecv failed\n");
    return 0;
  }

  if (msg.id != NET_CONF_MODULEREPLY || loader != NET_MODULE_LOADER_THREAD)
  {
    netdbgPrintf(NETDEBUG_MODULES,
                 "netModuleLookupException: bad reply message\n");
    return 0;
  }

  return msg.msg.netConf.ModuleReq.id;
}

NetModuleRegDesc lookupModuleRegistry = {
                                          NULL, NULL,
                                          MODULE_LOOKUP_TYPE,
                                          0,
                                          netModuleLookupMain,
                                          netModuleLookupConfig,
                                          netModuleLookupInit,
                                          "Modul Lookup"
                                        };
