/****************************************************************************/
/* Copyright (c) 2000 MBARI                                                 */
/* MBARI Proprietary Information. All rights reserved.                      */
/****************************************************************************/
/* Summary  :                                                               */
/* Filename : SharedObjectServer.h                                          */
/* Author   :                                                               */
/* Project  :                                                               */
/* Version  : 1.0                                                           */
/* Created  : 02/07/2000                                                    */
/* Modified :                                                               */
/* Archived :                                                               */
/****************************************************************************/
/* Modification History:                                                    */
/****************************************************************************/
#ifndef _SHAREDOBJECTSERVER_H
#define _SHAREDOBJECTSERVER_H

#include <unistd.h>
#include <sys/psinfo.h>
#include "DynamicArray.h"
#include "SharedObject.h"


/*
CLASS 
SharedObjectServer

DESCRIPTION
SharedObjectServer fills requests from SharedObjectClient objects

AUTHOR
Tom O'Reilly
*/

class SharedObjectServer : public SharedObject {

public:

  ////////////////////////////////////////////////////////////////////
  // Constructor
  // [input] name: Name of server. Clients find the server using this
  // name.
  SharedObjectServer(const char *name);
  virtual ~SharedObjectServer();

  ////////////////////////////////////////////////////////////////////
  // Run receive-process-reply loop
  virtual void run();

  class ServerExists : public Error {

  public:
    ServerExists(const char *serverName) : Error("") {
      sprintf(msg, "Server \"%s\" already exists", serverName);
    }
  };

protected:

  ////////////////////////////////////////////////////////////////////
  // Typedef for callback method. Method returns True if a reply is
  // to be made.
  typedef 
  Boolean (SharedObjectServer::*CallbackPtr)(Request *request, 
					     int nRequestBytes,
					     Reply **reply, 
					     int *nReplyBytes);

  ////////////////////////////////////////////////////////////////////
  // Register a callback function for specified SharedObject::RequestCode.
  // The callback should execute quickly, as the server cannot fill other
  // requests until the callback completes.
  void addCallback(SharedObject::RequestCode code, CallbackPtr callback);


  ////////////////////////////////////////////////////////////////////
  // Allocate request buffer
  virtual void allocateBuffers();

  ////////////////////////////////////////////////////////////////////
  // Maximum bytes in any request
  virtual size_t maxRequestBytes();

  ////////////////////////////////////////////////////////////////////
  // PID of current client
  pid_t clientPid();

  ////////////////////////////////////////////////////////////////////
  // Name of current client
  const char *clientName();
  
  Request *_requestPtr;


private:

  ////////////////////////////////////////////////////////////////////
  // Process the request depending on request code. Return True if
  // framework should reply.
  Boolean processRequest(Request *requestPtr, int nRequestBytes, 
			 Reply **replyPtr, int *nReplyBytes);

  ////////////////////////////////////////////////////////////////////
  // We keep a list of CallbackEntry objects. Each CallbackEntry 
  // specifies the callback function associated with a given RequestCode.
  struct CallbackEntry
  {
    CallbackEntry(SharedObject::RequestCode code, CallbackPtr callback) {
      _code = code;
      _callback = callback;
    }
    
    RequestCode _code;
    CallbackPtr _callback;
  };

  ////////////////////////////////////////////////////////////////////
  // PID of current client
  pid_t _clientPid;

  // Info on client process
  struct _psinfo _psInfo;

  ////////////////////////////////////////////////////////////////////
  // List of CallbackEntry objects
  DynamicArray <CallbackEntry *> _callbacks;

  int _processNameId;

  size_t _maxReqBytes;
};

#endif
