/****************************************************************************/
/* Copyright (c) 2000 MBARI                                                 */
/* MBARI Proprietary Information. All rights reserved.                      */
/****************************************************************************/
/* Summary  :                                                               */
/* Filename : EventService.cc                                               */
/* Author   :                                                               */
/* Project  :                                                               */
/* Version  : 1.0                                                           */
/* Created  : 02/07/2000                                                    */
/* Modified :                                                               */
/* Archived :                                                               */
/****************************************************************************/
/* Modification History:                                                    */
/****************************************************************************/
#include <string.h>
#include <malloc.h>
#include <errno.h>
#include <sys/kernel.h>
#include "EventService.h"
#include "Syslog.h"

EventService::EventService(const char *name, Task *task)
{
  _name = strdup(name);
  _task = task;
}


EventService::~EventService()
{
  free((void *)_name);
}


void EventService::subscribe(TaskInterface *client, 
			     EventCode eventCode,
			     Callback callback)
{
  client->subscribe(eventCode);
    
  EventTableEntry *entry = new EventTableEntry(client, eventCode, callback);
  _eventTable.add(&entry);
}


void EventService::processEvent()
{
  Boolean debug = False;
  TaskServer::Event event;

  // Wait for event notification
  pid_t senderPid = Receive(AnyPid, (void *)&event, sizeof(event));

  if (senderPid == -1) {

    if (errno == EINTR) {
      // Interrupted by signal; return
      dprintf("EventService::processEvent() - %s", strerror(errno));
      return;
    }
    else {
      Syslog::write("EventService::processEvent() - %s\n", strerror(errno));
      return;
    }

  }

  // Determine callback which corresponds to this notification
  Boolean found = False;
  for (int i = 0; i < _eventTable.size(); i++) {
    EventTableEntry *entry;
    _eventTable.get(i, &entry);

    if (event.eventCode == entry->_eventCode &&
	event.serverPid == entry->_proxy->serverPid()) {

      // Invoke callback
      dprintf("EventService::processEvent() - found callback\n");
      callMemberFunction(_task, entry->_callback)
	(entry->_proxy, event.eventCode);
      found = True;
    }
  }
  if (found) {
    if (qnx_proxy_detach(senderPid) == -1) {
      Syslog::write("EventService::processEvent() - %s\n", strerror(errno));
    }
  }

  if (!found) {
    syslog(LOG_ERR,
	   "EventService::processEvent() - unknown event, code=%d, pid=%d\n",
	   event.eventCode, event.serverPid);
  }
}



