//=========================================================================
// Summary  : */
// Filename : SharedObjectServer.h
// Author   : */
// Project  : */
// Revision : 1
// Created  : 2000/08/19
// Modified : 2000/08/19
//=========================================================================
// Description :
//=========================================================================
#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:

  //-----------------------------------------------------------------
  // Pure virtual method for initialization of all callbacks
  virtual int init() = 0;
  
  ////////////////////////////////////////////////////////////////////
  // 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();

  ////////////////////////////////////////////////////////////////////
  // 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;


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

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


private:
};

#endif
