420 lines
15 KiB
C++
Executable File
420 lines
15 KiB
C++
Executable File
|
|
// -----------------------------------------------------------------------------
|
|
// 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 service.
|
|
//
|
|
// Author: Walt Akers
|
|
//
|
|
// Revision History:
|
|
// cdevSimpleService.cc,v
|
|
// Revision 1.1 1996/11/21 18:22:24 akers
|
|
// Non-Server Oriented Service
|
|
//
|
|
// Revision 1.1 1996/04/30 15:37:38 akers
|
|
// Simple CDEV Service
|
|
//
|
|
// Revision 1.2 1996/03/21 13:57:55 akers
|
|
// Major Modifications
|
|
//
|
|
// Revision 1.1.1.1 1996/02/28 16:36:21 akers
|
|
// Initial release of support for ACE Services
|
|
//
|
|
// -----------------------------------------------------------------------------
|
|
|
|
#include <cdevSimpleService.h>
|
|
#include <cdevSimpleRequestObject.h>
|
|
#include <cdevClock.h>
|
|
#include <ctype.h>
|
|
|
|
// *****************************************************************************
|
|
// * defaultCallback:
|
|
// * This static function is the default callback function that will be
|
|
// * utilized for send and sendNoBlock.
|
|
// *****************************************************************************
|
|
static void defaultCallback(int, void *, cdevRequestObject &, cdevData &)
|
|
{
|
|
}
|
|
|
|
|
|
// *****************************************************************************
|
|
// * trim :
|
|
// * This method is used to remove any extraneous spaces from a message.
|
|
// *****************************************************************************
|
|
static char * trim ( char * ptr )
|
|
{
|
|
char * s1 = ptr;
|
|
char * s2;
|
|
|
|
if(ptr!=NULL)
|
|
{
|
|
// *************************************************************
|
|
// * Remove leading space from the string.
|
|
// *************************************************************
|
|
for(s1=ptr; isspace(*s1) && s1!=0; s1++);
|
|
if(s1!=ptr) memmove(ptr, s1, strlen(s1)+1);
|
|
|
|
// *************************************************************
|
|
// * Remove any multi-space entries from the string.
|
|
// *************************************************************
|
|
for(s1=ptr; *s1; s1++) if(isspace(*s1))
|
|
{
|
|
for(s2=s1; *s2 && isspace(*s2); s2++);
|
|
if(s2>s1+1) memmove(s1+1, s2, strlen(s2)+1);
|
|
}
|
|
|
|
// *************************************************************
|
|
// * Remove trailing space from the string.
|
|
// *************************************************************
|
|
for(s1=&ptr[strlen(ptr)-1]; s1>=ptr && isspace(*s1); s1--) *s1=0;
|
|
}
|
|
|
|
return ptr;
|
|
}
|
|
|
|
// *****************************************************************************
|
|
// * cdevSimpleService::cdevSimpleService :
|
|
// * This constructor is responsible for performing all service
|
|
// * initialization.
|
|
// *****************************************************************************
|
|
cdevSimpleService::cdevSimpleService ( char * name, cdevSystem & system )
|
|
: serviceFD(-1),
|
|
queue(),
|
|
selector(),
|
|
callback(defaultCallback, NULL),
|
|
cdevService(name, system)
|
|
{
|
|
// *********************************************************************
|
|
// * Install the ACE_service specific flags
|
|
// *********************************************************************
|
|
installTags();
|
|
|
|
// *********************************************************************
|
|
// * Clear local variables
|
|
// *********************************************************************
|
|
memset(&serviceFD, 0, sizeof(serviceFD));
|
|
|
|
// *********************************************************************
|
|
// * Assign the value of the read file descriptor for the selector to
|
|
// * the serviceFD variable.
|
|
// *********************************************************************
|
|
serviceFD = selector.readfd();
|
|
}
|
|
|
|
|
|
// *****************************************************************************
|
|
// * 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::~cdevSimpleService ( void )
|
|
{
|
|
// *********************************************************************
|
|
// * Call flush to process all outbound messages.
|
|
// *********************************************************************
|
|
flush();
|
|
|
|
// *********************************************************************
|
|
// * Clear the file descriptors used by cdev for polling.
|
|
// *********************************************************************
|
|
memset(&serviceFD, 0, sizeof(serviceFD));
|
|
}
|
|
|
|
|
|
// *****************************************************************************
|
|
// * 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 cdevSimpleService::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 cdevSimpleService::getRequestObject ( char * device, char * message, cdevRequestObject * &req)
|
|
{
|
|
req = new cdevSimpleRequestObject (device, message, system_);
|
|
return (req ? CDEV_SUCCESS : CDEV_ERROR);
|
|
}
|
|
|
|
// *****************************************************************************
|
|
// * 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 cdevSimpleService::getFd ( int * &fd, int & numFd )
|
|
{
|
|
fd = &serviceFD;
|
|
numFd = 1;
|
|
|
|
return CDEV_SUCCESS;
|
|
}
|
|
|
|
|
|
// *********************************************************************
|
|
// * 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 cdevSimpleService::flush ( void )
|
|
{
|
|
return CDEV_SUCCESS;
|
|
}
|
|
|
|
|
|
// *****************************************************************************
|
|
// * 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 cdevSimpleService::poll ( void )
|
|
{
|
|
return pend(0.0001);
|
|
}
|
|
|
|
|
|
|
|
// *****************************************************************************
|
|
// * 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 cdevSimpleService::pend ( int )
|
|
{
|
|
while(!queue.empty()) handleOneEvent();
|
|
|
|
// *********************************************************************
|
|
// * Empty the contents of the cdevSelector object.
|
|
// *********************************************************************
|
|
selector.purge();
|
|
|
|
return CDEV_SUCCESS;
|
|
}
|
|
|
|
|
|
|
|
// *****************************************************************************
|
|
// * 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 cdevSimpleService::pend ( double seconds, int )
|
|
{
|
|
cdevTimeValue sec = seconds;
|
|
cdevClock timer;
|
|
|
|
timer.schedule(NULL, sec);
|
|
|
|
do {
|
|
handleOneEvent();
|
|
} while(!timer.expired() && !queue.empty());
|
|
|
|
// *********************************************************************
|
|
// * Empty the contents of the cdevSelector object.
|
|
// *********************************************************************
|
|
return CDEV_SUCCESS;
|
|
}
|
|
|
|
|
|
// *****************************************************************************
|
|
// * 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.
|
|
// *****************************************************************************
|
|
int cdevSimpleService::submit (cdevTranNode *node,
|
|
char *device,
|
|
char *message,
|
|
cdevData *data)
|
|
{
|
|
cdevTransaction * transaction = new cdevTransaction;
|
|
cdevServiceMessage * packet;
|
|
|
|
// *********************************************************************
|
|
// * Populate the cdevTransaction structure with data.
|
|
// *********************************************************************
|
|
transaction->transnum = node->transaction();
|
|
transaction->transobj = node;
|
|
|
|
// *********************************************************************
|
|
// * Call trim on the device and message to remove any extra spaces.
|
|
// *********************************************************************
|
|
trim(device);
|
|
trim(message);
|
|
|
|
// *********************************************************************
|
|
// * Populate the packet variable with the data.
|
|
// *********************************************************************
|
|
|
|
packet = new cdevServiceMessage(transaction, device, message, data);
|
|
|
|
// *********************************************************************
|
|
// * Place the cdevServiceMessage into the queue.
|
|
// *********************************************************************
|
|
queue.enqueue(packet);
|
|
|
|
// *********************************************************************
|
|
// * Add an event to the cdevSelector object in order to trigger polling
|
|
// *********************************************************************
|
|
selector.insertEvent();
|
|
|
|
return CDEV_SUCCESS;
|
|
}
|
|
|
|
|
|
|
|
// *****************************************************************************
|
|
// * 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.
|
|
// *****************************************************************************
|
|
int cdevSimpleService::dequeue (cdevTransaction * &transaction,
|
|
char * &device,
|
|
char * &message,
|
|
cdevData * &data)
|
|
{
|
|
int result = CDEV_ERROR;
|
|
cdevServiceMessage * packet = (cdevServiceMessage *)queue.dequeue();
|
|
|
|
if(packet!=NULL)
|
|
{
|
|
transaction = packet->transaction;
|
|
device = packet->device;
|
|
message = packet->message;
|
|
data = packet->data;
|
|
result = CDEV_SUCCESS;
|
|
delete packet;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
// *****************************************************************************
|
|
// * cdevSimpleService::enqueue :
|
|
// * The handleOneEvent method uses this function to dispatch callbacks
|
|
// * after the function has been processed.
|
|
// *****************************************************************************
|
|
int cdevSimpleService::enqueue (int status,
|
|
cdevTransaction * trans,
|
|
char * device,
|
|
char * message,
|
|
cdevData * data)
|
|
{
|
|
cdevTranNode * node = trans?trans->transobj:NULL;
|
|
|
|
if(node!=NULL && node->validate(trans->transnum)==CDEV_SUCCESS)
|
|
{
|
|
cdevData localData;
|
|
|
|
// *************************************************************
|
|
// * cdevData must be returned to the caller.
|
|
// *************************************************************
|
|
if(node->resultData_==NULL) node->resultData_ = (data?data:&localData);
|
|
else *(node->resultData_) = (data?*data:localData);
|
|
|
|
// *************************************************************
|
|
// * Call the user provided callback function.
|
|
// *************************************************************
|
|
(node->userCallback_->callbackFunction())
|
|
(status,
|
|
node->userCallback_->userarg(),
|
|
*node->reqObj_,
|
|
*node->resultData_);
|
|
|
|
// *************************************************************
|
|
// * Tag the transaction as finished
|
|
// *************************************************************
|
|
node->finished(1);
|
|
|
|
// *************************************************************
|
|
// * Delete the cdevTranNode if it is not permanent.
|
|
// *************************************************************
|
|
if(!node->permanent()) delete node;
|
|
|
|
// *************************************************************
|
|
// * Remove the event from the selector object.
|
|
// *************************************************************
|
|
selector.removeEvent();
|
|
}
|
|
|
|
// *********************************************************************
|
|
// * Delete the components of the message.
|
|
// *********************************************************************
|
|
if(trans != NULL) delete trans;
|
|
if(device != NULL) delete device;
|
|
if(message != NULL) delete message;
|
|
if(data != NULL) delete data;
|
|
|
|
return CDEV_SUCCESS;
|
|
}
|
|
|
|
|
|
// *****************************************************************************
|
|
// * cdevSimpleService::handleOneEvent :
|
|
// * This method allows the caller to handle individual events. This handler
|
|
// * only processes one event and then returns to the caller.
|
|
// *****************************************************************************
|
|
void cdevSimpleService::handleOneEvent ( void )
|
|
{
|
|
cdevTransaction * transaction;
|
|
char * device;
|
|
char * message;
|
|
cdevData * data;
|
|
|
|
if(dequeue(transaction, device, message, data)==CDEV_SUCCESS)
|
|
{
|
|
enqueue(CDEV_SUCCESS, transaction, device, message, data);
|
|
}
|
|
}
|
|
|
|
|
|
// *****************************************************************************
|
|
// * cdevSimpleService::getNameServer :
|
|
// * This function should obtain the default name server for this object.
|
|
// * It does nothing for now.
|
|
// *****************************************************************************
|
|
int cdevSimpleService::getNameServer(cdevDevice * &ns)
|
|
{
|
|
ns = 0;
|
|
return CDEV_SUCCESS;
|
|
}
|
|
|