Files
cdev-1.7.2n/extensions/SimpleService/cdevSimpleService.cc
2022-12-13 12:44:04 +01:00

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