
// -----------------------------------------------------------------------------
// Copyright (c) 1995      Southeastern Universities Research Association,
//                         Continuous Electron Beam Accelerator Facility
//
// This software was developed under a United States Government license
// described in the NOTICE file included as part of this distribution.
//
// -----------------------------------------------------------------------------
//
// Description:
//	This header file contains the class definitions for the classes
//	associated with the construction of a model service.
//
// Author:  Walt Akers
//
// -----------------------------------------------------------------------------

#if !defined (_CDEV_SIMPLE_SERVICE_H_)
#define _CDEV_SIMPLE_SERVICE_H_

#include <cdevService.h>
#include <cdevTranNode.h>
#include <cdevSelector.h>
#include <fifo.h>

// ****************************************************************************
// * Service Loader:
// *	The first step in building a new service is to construct a service 
// *	loader function.  This function will allow cdev to dynamically
// *	initialize a service by name.   
// *	
// *	The function should adhere to the following naming convention...
// *		cdevService * newXXX (char * name, cdevSystem * system);
// *
// *		The 'XXX' should be replaced with the name of the service
// *		class.
// *
// *	The function should also be declared as 'extern "C"' to allow it 
// *	to be called and loaded from within an external shared library module.
// *
// *	This function serves only to construct a new instance of the
// *	specified service, and return it to the instanciating mechanism.
// *****************************************************************************
// extern "C" cdevService *newcdevSimpleService ( char * name, cdevSystem * system );

// *****************************************************************************
// * This structure is used to maintain a cdevTranNode class and its matching
// * transaction number.  The transaction number will be used to validate
// * the cdevTranNode later.
// *****************************************************************************
typedef struct
	{
	int            transnum;
	cdevTranNode * transobj;
	} cdevTransaction;


// ******************************************************************************
// * This is a structure that is used to store the components that are placed in 
// * the queues.
// ******************************************************************************
class cdevServiceMessage
{
public:
	cdevTransaction * transaction;
	char            * device;
	char            * message;
	cdevData        * data;

	cdevServiceMessage(cdevTransaction *Transaction=NULL, 
			   char            *Device=NULL, 
			   char            *Message=NULL, 
			   cdevData        *Data=NULL)
		: transaction(Transaction), 
		  device(Device), 
		  message(Message), 
		  data(Data)
		{
		}			
	};

	

// *****************************************************************************
// * cdevSimpleService:
// *	This is class provides the mechanisms that the cdev system will use
// *	to communicate with the model service.
// *****************************************************************************
class cdevSimpleService : public cdevService
{
friend class cdevSimpleRequestObject;

public:
	// *********************************************************************
	// * cdevSimpleService::cdevSimpleService :
	// *	This constructor is responsible for performing all service
	// *	initialization.
	// *********************************************************************
	cdevSimpleService ( char * name, cdevSystem & system );

	// *********************************************************************
	// * cdevSimpleService::~cdevSimpleService :
	// *	The destructor is protected to prevent it from being called 
	// * 	directly. The destructor performs any clean-up or shutdown 
	// * 	operations.
	// *
	// *	Returns nothing.
	// *********************************************************************
	~cdevSimpleService ( void );

	// *********************************************************************
	// * cdevSimpleService::installTags :
	// *	Installs the tags that the service and service applications
	// *	will use.  This function is static to allow servers to setup
	// *	the necessary tags without having to instanciate a 
	// * 	cdevSimpleService object.
	// *********************************************************************
	void installTags ( void );	
	
	// *********************************************************************
	// * cdevSimpleService::getRequestObject :
	// *	This is the interface that cdev objects will use to obtain a
	// *	cdevSimpleRequestObject object.  The cdevSimpleRequestObject 
	// *	represents a combined device and message pair that is associated 
	// *	with the cdevSimpleService.
	// *
	// *	Returns CDEV_SUCCESS on success or CDEV_ERROR on error.
	// *********************************************************************
	int getRequestObject (char *, char *, cdevRequestObject * &);

	// *********************************************************************
	// * cdevSimpleService::getFd
	// *	This function will return the list of file descriptors that the
	// *	cdevSimpleService is using.  This will allow the file 
	// *	descriptors to be used in global select and poll calls performed
	// *	at the cdevSystem class level.
	// *
	// *	Returns CDEV_SUCCESS on success or CDEV_ERROR on error.
	// *********************************************************************
	int getFd ( int * &fd, int & numFd );

	// *********************************************************************
	// * cdevSimpleService::flush :
	// *	This function flushes all communications buffers that the 
	// *	service may have open.
	// *
	// *	Returns CDEV_SUCCESS on success or CDEV_ERROR on error.
	// *********************************************************************
	int flush ( void );

	// *********************************************************************
	// * cdevSimpleService::poll :
	// *	This function polls the file descriptors used by the service
	// *	until one of them becomes active or a discrete amount of time
	// *	has expired.
	// *
	// *	Returns CDEV_SUCCESS on success or CDEV_ERROR on error.
	// *********************************************************************
	int poll ( void );

	// *********************************************************************
	// * cdevSimpleService::pend :
	// *	Pends until the named file descriptor (or any file descriptor
	// *	if fd = -1) is ready.  Will pend for no longer than the user
	// *	specified number of seconds.
	// *
	// *	Returns CDEV_SUCCESS on success or CDEV_ERROR on error.
	// *********************************************************************
	int pend ( double seconds, int = -1);

	// *********************************************************************
	// * cdevSimpleService::pend :
	// *	Pends until the named file descriptor (or any file descriptor
	// *	if fd =  -1) is ready.  Will pend forever if the descriptor does
	// *	not become active.
	// *
	// *	Returns CDEV_SUCCESS on success or CDEV_ERROR on error.
	// *********************************************************************
	int pend ( int = -1);

	// *********************************************************************
	// * cdevSimpleService::submit :
	// *	This is the mechanism that the request object will use to submit
	// *	a message to the service.  It is important to note that all of 
	// *	the data provided to this object becomes the property of the 
	// *	service and must not be accessed afterwords.
	// *********************************************************************
	virtual int submit (cdevTranNode *, char *, char *, cdevData *);		

	// *********************************************************************
	// * cdevSimpleService::dequeue :
	// *	The handleOneEvent method uses this function to extract a single
	// *	message from the service and process it.  All data objects 
	// *	obtained through this function become the property of the caller 
	// *	and must be deleted.
	// *********************************************************************
	virtual int dequeue (cdevTransaction * &, char * &, char * &, cdevData * &);
	
	// *********************************************************************
	// * cdevSimpleService::enqueue :
	// *	The handleOneEvent method uses this function to dispatch 
	// *	callbacks after the function has been processed.
	// *********************************************************************
	virtual int enqueue (int, cdevTransaction *, char *, char *, cdevData *);

	// *********************************************************************
	// * cdevSimpleService::handleOneEvent :
	// *	This method allows the caller to handle individual events.  This
	// *	handler only processes one event and then returns to the caller.
	// *********************************************************************
	virtual void handleOneEvent ( void );

	// *********************************************************************
	// * cdevSimpleService::getNameServer :
	// *	This function should obtain the default name server for this 
	// *	object.  It does nothing for now.
	// *********************************************************************
	int getNameServer(cdevDevice * &ns);

	
private:
	FifoQueue             queue;
	int                   serviceFD;
	cdevSelector          selector;
	cdevCallback          callback;
};

#endif /* _CDEV_SIMPLE_SERVICE_H_ */
