cdev-1.7.2n

This commit is contained in:
2022-12-13 12:44:04 +01:00
commit b3b88fc333
1357 changed files with 338883 additions and 0 deletions
Binary file not shown.
+373
View File
@@ -0,0 +1,373 @@
service CLIP {
tags {server, host, port}
}
class ca {
verbs {get, set, monitorOn, monitorOff}
attributes {
VAL CLIP {server=Gateway1, host=devsrv.cebaf.gov, port=9199};
XPOS CLIP {server=Gateway1, host=devsrv.cebaf.gov, port=9199};
YPOS CLIP {server=Gateway1, host=devsrv.cebaf.gov, port=9199};
ServerInfo CLIP {server=Gateway1, host=devsrv.cebaf.gov, port=9199};
ClientInfo CLIP {server=Gateway1, host=devsrv.cebaf.gov, port=9199};
}
}
class ModelClass
{
verbs {get, set, monitorOn, monitorOff}
attributes {
elements CLIP {server=GOLD, host=mdlsrv.cebaf.gov, port=9000};
sections CLIP {server=GOLD, host=mdlsrv.cebaf.gov, port=9000};
ServerInfo CLIP {server=GOLD, host=mdlsrv.cebaf.gov, port=9000};
ClientInfo CLIP {server=GOLD, host=mdlsrv.cebaf.gov, port=9000};
}
}
ModelClass : model ;
ca : IPM1R01
IPM1R02
IPM1R03
IPM1R04
IPM1R06
IPM1R08
IPM1R09
IPM1R10
IPM1S01
IPM1S02
IPM1S03
IPM1S05
IPM1S07
IPM1S08
IPM1S09
IPM1S10
IPM2R01
IPM2R02
IPM2R03
IPM2R04
IPM2R06
IPM2R08
IPM2R09
IPM2R10
IPM2S01
IPM2S02
IPM2S03
IPM2S07
IPM2S08
IPM2S09
IPM2T00A
IPM2T00B
IPM2T01
IPM2T03
IPM2T06
IPM2T07
IPM2T08
IPM2T09
IPM3A02
IPM3A03
IPM3A05
IPM3A07
IPM3A08
IPM3A09
IPM3A10
IPM3A11
IPM3A13
IPM3A15
IPM3A16
IPM3A17
IPM3A18
IPM3A19
IPM3A21
IPM3A23
IPM3A24
IPM3A25
IPM3A26
IPM3A27
IPM3A29
IPM3A31
IPM3A32
IPM3E01
IPM3E03
IPM3R01
IPM3R02
IPM3R03
IPM3R04
IPM3R06
IPM3R08
IPM3R09
IPM3R10
IPM3S01
IPM3S02
IPM3S03
IPM3S05
IPM3S07
IPM3S08
IPM3S09
IPM3S10
IPM4A02
IPM4A03
IPM4A05
IPM4A07
IPM4A08
IPM4A09
IPM4A10
IPM4A11
IPM4A13
IPM4A15
IPM4A16
IPM4A17
IPM4A18
IPM4A19
IPM4A21
IPM4A23
IPM4A24
IPM4A25
IPM4A26
IPM4A27
IPM4A29
IPM4A31
IPM4A32
IPM4E03
IPM4R01
IPM4R02
IPM4R03
IPM4R04
IPM4R06
IPM4R08
IPM4R09
IPM4R10
IPM4S01
IPM4S02
IPM4S03
IPM4S07
IPM4S09
IPM4T00A
IPM4T00B
IPM4T01
IPM4T03
IPM4T06
IPM4T07
IPM4T08
IPM4T09
IPM5A02
IPM5A03
IPM5A05
IPM5A07
IPM5A08
IPM5A09
IPM5A10
IPM5A11
IPM5A13
IPM5A15
IPM5A16
IPM5A17
IPM5A18
IPM5A19
IPM5A21
IPM5A23
IPM5A24
IPM5A25
IPM5A26
IPM5A27
IPM5A29
IPM5A31
IPM5A32
IPM5E01
IPM5E03
IPM5R01
IPM5R02
IPM5R03
IPM5R04
IPM5R06
IPM5R08
IPM5R09
IPM5R10
IPM5S01
IPM5S02
IPM5S03
IPM5S05
IPM5S07
IPM5S08
IPM5S09
IPM5S10
IPM6A02
IPM6A03
IPM6A05
IPM6A07
IPM6A08
IPM6A09
IPM6A10
IPM6A11
IPM6A13
IPM6A15
IPM6A16
IPM6A17
IPM6A18
IPM6A19
IPM6A21
IPM6A23
IPM6A24
IPM6A25
IPM6A26
IPM6A27
IPM6A29
IPM6A31
IPM6A32
IPM6E03
IPM6R01
IPM6R02
IPM6R03
IPM6R04
IPM6R06
IPM6R08
IPM6R09
IPM6R10
IPM6S01
IPM6S02
IPM6S03
IPM6S07
IPM6S09
IPM6T00A
IPM6T00B
IPM6T01
IPM6T03
IPM6T06
IPM6T07
IPM6T08
IPM6T09
IPM7A02
IPM7A03
IPM7A05
IPM7A07
IPM7A08
IPM7A09
IPM7A10
IPM7A11
IPM7A13
IPM7A15
IPM7A16
IPM7A17
IPM7A18
IPM7A19
IPM7A21
IPM7A23
IPM7A24
IPM7A25
IPM7A26
IPM7A27
IPM7A29
IPM7A31
IPM7A32
IPM7E01
IPM7E03
IPM7R01
IPM7R02
IPM7R03
IPM7R04
IPM7R06
IPM7R08
IPM7R09
IPM7R10
IPM7S01
IPM7S02
IPM7S03
IPM7S05
IPM7S07
IPM7S08
IPM7S09
IPM7S10
IPM8A02
IPM8A03
IPM8A05
IPM8A07
IPM8A08
IPM8A09
IPM8A10
IPM8A11
IPM8A13
IPM8A15
IPM8A16
IPM8A17
IPM8A18
IPM8A19
IPM8A21
IPM8A23
IPM8A24
IPM8A25
IPM8A26
IPM8A27
IPM8A29
IPM8A31
IPM8A32
IPM8E03
IPM8R01
IPM8R02
IPM8R03
IPM8R04
IPM8R06
IPM8R08
IPM8R09
IPM8R10
IPM8S01
IPM8S02
IPM8S03
IPM8S07
IPM8S08
IPM8T00A
IPM8T00B
IPM8T01
IPM8T03
IPM8T06
IPM8T07
IPM8T08
IPM8T09
IPM9A02
IPM9A03
IPM9A05
IPM9A07
IPM9A08
IPM9A09
IPM9A10
IPM9A11
IPM9A13
IPM9A15
IPM9A16
IPM9A17
IPM9A18
IPM9A19
IPM9A21
IPM9A23
IPM9A24
IPM9A25
IPM9A26
IPM9A27
IPM9A29
IPM9A31
IPM9A32
IPM9E01
IPM9E03
IPM9R01
IPM9R02
IPM9R03
IPM9R04
IPM9R05
IPM9R07
IPM9R08
IPM9S01
IPM9S02
IPM9S04
IPM9S05
IPM9S06
IPM9S07
IPM9S08
IPMAS00
IPMAT02
IPMAT07
IPMAT09
IPMNS01
IPMNS04
IPMNS05
IPMNS06
;
@@ -0,0 +1,47 @@
#include <cdevSystem.h>
#include <cdevDirectory.h>
#include <CLIPService.h>
#include <CLIPRequestObject.h>
CLIPRequestObject::CLIPRequestObject ( char * device, char * message, cdevSystem & system)
: cdevClientRequestObject(device, message, system)
{
cdevData output;
*host = 0;
port = 0;
sprintf (host, "resolveServiceData %s %s", device, message);
if((system.nameServer()).send(host, NULL, &output)==CDEV_SUCCESS)
{
*host = 0;
output.get ("host", host, 256);
output.get ("port", &port);
}
else *host = 0;
}
int CLIPRequestObject::getServerHandler ( ServerHandler ** Handler )
{
CLIPService * svc = (CLIPService *)service_;
int result = CDEV_SUCCESS;
*Handler = NULL;
if (*server==0 && *DDL_server!=0) strcpy(server, DDL_server);
if (*server!=0 && handler==NULL)
{
if((*Handler = svc->connect(server,
(*host)?host:(char *)NULL,
(*host)?port:0))==NULL) result = CDEV_ERROR;
else
{
handler = *Handler;
handler->registerServerCallback(this);
}
}
else *Handler = handler;
return result;
}
@@ -0,0 +1,14 @@
#include <cdevClientRequestObject.h>
class CLIPRequestObject : public cdevClientRequestObject
{
protected:
char host [256];
unsigned short port;
public:
CLIPRequestObject ( char *device, char * message,
cdevSystem & system = cdevSystem::defaultSystem());
virtual int getServerHandler ( ServerHandler ** Handler );
};
+247
View File
@@ -0,0 +1,247 @@
#include <CLIPService.h>
#include <CLIPRequestObject.h>
#include <cdevMessage.h>
// *****************************************************************************
// * newCLIPService:
// * This function will be called by the cdevSystem object to create an
// * initial instance of the CLIPService.
// *****************************************************************************
extern "C" cdevService * newCLIPService (char * name, cdevSystem * system)
{
return new CLIPService(name, *system);
}
void NULLError (int, char *, cdevRequestObject *)
{
}
// *****************************************************************************
// * CLIPService::CLIPService :
// * This is the constructor for the CLIPService. It initializes the
// * underlying CLIPService by specifying that it is in the domain of
// * VIRTUAL.
// *****************************************************************************
CLIPService::CLIPService ( char * name, cdevSystem & system)
: cdevClientService("CLIP", name, system)
{
system.reportError(CDEV_SEVERITY_INFO, "CLIPService", NULL,
"Constructing a new CLIPService");
}
// *****************************************************************************
// * CLIPService::getRequestObject :
// * This is the interface that cdev objects will use to obtain a
// * CLIPRequestObject object. The CLIPRequestObject
// * represents a combined device and message pair that is associated
// * with the CLIPService.
// *
// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error.
// *****************************************************************************
int CLIPService::getRequestObject ( char * device, char * message, cdevRequestObject * &req)
{
req = new CLIPRequestObject (device, message, system_);
return (req ? CDEV_SUCCESS : CDEV_ERROR);
}
// *****************************************************************************
// * CLIPService::connect :
// * This mechanism will establish a new connection with a server and will
// * will return a pointer to the ServerHandler. If the host and port are
// * specified in the arguments, then the method will attempt to connect
// * using those values without going through the CDEV Name Server.
// *
// * Note: This method will insert the ServerHandler into the connections
// * object and will install it in the Reactor.
// *****************************************************************************
ServerHandler * CLIPService::connect ( char * server, char * host, short port )
{
ServerHandler * handler = NULL;
// *********************************************************************
// * First attempt to locate the handler from the existing connections.
// *********************************************************************
if(server && *server && (handler = connections.find(server))==NULL)
{
int errCode = CDEV_SUCCESS;
char serverHost[255];
short serverPort;
int serverStatus;
int hostMatchesNS;
// *************************************************************
// * Initialize these values to reflect a server that is not
// * defined within the name server.
// *************************************************************
*serverHost = 0;
serverPort = 0;
serverStatus = 2;
hostMatchesNS = 0;
// *************************************************************
// * Raise the error threshold to reduce noise while the service
// * tries to resolve the location of the server.
// *************************************************************
system_.setThreshold(100);
// *************************************************************
// * In this implementation we will always attempt to resolve
// * the location of the server using the name server first, to
// * determine if monitoring can be installed later...
// *************************************************************
cdevData input;
cdevData output;
cdevRequestObject & rnsReq =
cdevRequestObject::attachRef("NameServer", "get");
// *****************************************************
// * Insert domain and name in the input request object
// * to be sent to the CDEV Name Server.
// *****************************************************
input.insert("name", server);
input.insert("domain", domain);
// *****************************************************
// * Query the Name Server to obtain the hostname and
// * port of the specified domain and server.
// *****************************************************
if(rnsReq.send(input, output)==CDEV_SUCCESS)
{
output.get("host", serverHost, 255);
output.get("port", &serverPort);
output.get("status", &serverStatus);
}
// *************************************************************
// * Restore the error threshold to a reasonable level.
// *************************************************************
system_.setThreshold(CDEV_SEVERITY_ERROR);
// *************************************************************
// * If the host and port have been specified, then use them
// * rather than going through the CDEV Name Server.
// *************************************************************
if(host!=NULL && *host && port>0)
{
if(strcmp(serverHost, host) && serverPort==port)
hostMatchesNS = 1;
strcpy(serverHost, host);
serverPort = port;
}
else {
if(*serverHost == 0 || serverPort<=0 || serverStatus!=0)
{
errCode = CDEV_ERROR;
// *********************************************
// * If the hostname could not be found, report
// * the error and set the return value to
// * CDEV_ERROR.
// *********************************************
outputError(CDEV_SEVERITY_ERROR,
"CLIPService::connect",
"Cannot find host for server \"%s\" in domain \"%s\"",
server, domain);
}
else hostMatchesNS = 1;
}
// *************************************************************
// * If the hostname was discovered, then the errCode should be
// * CDEV_SUCCESS. Attempt to connect to the server using the
// * cdevReactor mechanisms.
// *************************************************************
if(errCode==CDEV_SUCCESS)
{
cdevInetAddr addr;
addr.set (serverPort, serverHost);
handler = new ServerHandler(server, this);
if(handler->open(addr)!=0)
{
outputError(CDEV_SEVERITY_ERROR,
"CLIPService::connect",
"Failed to connect to %s on port %i",
serverHost,
serverPort);
delete handler;
handler = NULL;
}
else {
outputError(CDEV_SEVERITY_INFO,
"CLIPService::connect",
"Connected to %s on port %i",
serverHost,
serverPort);
connections.insert(handler);
// *********************************************
// * This calls the registerFd method of the
// * service which will cause the FD Changed
// * callbacks to be triggered.
// *********************************************
registerFd(handler->getHandle(), 1);
// *********************************************
// * Install a Name Server monitor to maintain
// * the status of the connection.
// * Note: If a monitor has already been
// * installed using this informations, then the
// * CDEV Name Server service should not create
// * a second monitor.
// *
// * Note: I am using the FifoQueue associated
// * with the specific server in order to
// * differentiate between the various servers.
// *********************************************
if(hostMatchesNS)
{
cdevData monData;
cdevCallback monCb(nameServerCallback, (void *)getCallbackArg(server));
cdevRequestObject & monReq = cdevRequestObject::attachRef("NameServer", "monitorOn");
monData.insert("name", server);
monData.insert("domain", domain);
monReq.sendCallback(monData, monCb);
}
// *********************************************
// * Here is where a "set ClientInfo" message
// * will be sent to the server to provide
// * descriptive information about the client.
// *********************************************
cdevData tagMap;
int * tags;
char ** ctags;
int ntags;
char * binary = NULL;
size_t binaryLen = 0;
cdevData::readTagTable(tags, ctags, ntags);
tagMap.insert(1, tags, ntags);
tagMap.insert(2, ctags, ntags);
delete tags;
delete ctags;
handler->setTagChangeFlag(0);
cdevMessageBinary packet(handler->getClientID(),
0, 0, 0, 0, CDEV_SERVER_OP, 0, 0,
NULL, "set ClientInfo",
&clientInfo.getClientData(),
NULL, &tagMap);
packet.streamOut(&binary, &binaryLen);
packet.detachData();
ServerInterface::enqueue(handler, binary, binaryLen);
}
}
}
return handler;
}
+24
View File
@@ -0,0 +1,24 @@
#include <cdevClientService.h>
// *****************************************************************************
// * newCLIPService :
// * This function will be called by the cdevSystem object to create an
// * initial instance of the CLIPService.
// *****************************************************************************
extern "C" cdevService * newCLIPService ( char * name, cdevSystem * system );
// *****************************************************************************
// * class CLIPService :
// * This class simply inherits from the cdevClientService and must define
// * only a constructor and destructor.
// *****************************************************************************
class CLIPService : public cdevClientService
{
public:
CLIPService ( char * name, cdevSystem & system = cdevSystem::defaultSystem());
virtual ServerHandler * connect ( char * server, char * host = NULL, short port = 0 );
virtual int getRequestObject ( char * device, char * message, cdevRequestObject * &req);
protected:
virtual ~CLIPService ( void ) {};
};
+16
View File
@@ -0,0 +1,16 @@
service CLIP {
tags {server, host, port}
}
class JAVAServer {
verbs {get, set, monitorOn, monitorOff}
attributes {
Thing1 CLIP {server=JServer1, host=localhost, port=9900};
Thing2 CLIP {server=JServer1, host=localhost, port=9900};
}
}
JAVAServer :
JServer1
;
+30
View File
@@ -0,0 +1,30 @@
ARCH = OS
SHOBJ = YES
include $(CDEV)/extensions/cdevGenericServer/include/makeinclude/Makefile.$(ARCH)
APPNAME = "CDEV CLIP Client/Service"
CXXINCLUDES = -I./
# ******************************************************************************
# * The BINARIES definition names all of the binary files that should be deleted
# * whenever "make clean" is executed.
# ******************************************************************************
BINARIES = $(BASELIB)/libCLIPService.a \
$(BASELIB)/CLIPService.so
ifeq ($(SHOBJ), YES)
LIBS = -L$(CDEVLIB) -lcdevGenericServer $(CDEVLIBS) $(OSLIBS)
TARGETS = $(BASELIB)/CLIPService.so
else
LIBS = -L$(CDEVLIB) -lcdevGenericServer $(CDEVLIBS) $(OSLIBS)
TARGETS = $(BASELIB)/libCLIPService.a
endif
targets : $(TARGETS)
$(BASELIB)/CLIPService.so : $(OBJDIR)/CLIPService.o $(OBJDIR)/CLIPRequestObject.o
$(LINK.so) -o $@ $^ -L$(CDEVLIB) -lcdevGenericServer $(NETLIBS)
@mkdir -p $(CDEVSHOBJ)/$(CDEVVERSION)
@cp $@ $(CDEVSHOBJ)/$(CDEVVERSION)/$(@F)
+74
View File
@@ -0,0 +1,74 @@
=> Building [Linux] in CDEV CLIP Client/Service
=> g++ -c CLIPService.cc -o CLIPService.o
target is .shobj/Linux/CLIPService.o and CLIPService.cc
/home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/fifo.h: In function `static class QueueBase::node * QueueBase::newNode()':
In file included from /home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/ServerHandler.h:17,
from /home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/ServerInterface.h:5,
from /home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/cdevClientService.h:7,
from CLIPService.h:1,
from CLIPService.cc:1:
/home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/fifo.h:76: warning: ANSI C++ forbids implicit conversion from `void *' in assignment
/home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/StringHash.h: In method `char * StringHashIterator::key()':
In file included from /home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/ServerInterface.h:7,
from /home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/cdevClientService.h:7,
from CLIPService.h:1,
from CLIPService.cc:1:
/home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/StringHash.h:227: warning: ANSI C++ forbids implicit conversion from `void *' in return
/home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/ServerInterface.h: In method `class ServerHandler * ServerConnectionList::operator [](int)':
In file included from /home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/cdevClientService.h:7,
from CLIPService.h:1,
from CLIPService.cc:1:
/home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/ServerInterface.h:30: warning: ANSI C++ forbids implicit conversion from `void *' in return
/home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/cdevContextMap.h: In method `class cdevData * cdevContextMap::find(int)':
In file included from /home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/cdevClientService.h:9,
from CLIPService.h:1,
from CLIPService.cc:1:
/home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/cdevContextMap.h:28: warning: ANSI C++ forbids implicit conversion from `void *' in return
/home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/cdevClientService.h: In method `class ServerHandler * CLIPService::connect(char *, char * = 0, short int = 0)':
/home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/cdevClientService.h:99: method `class NSCallbackArg * cdevClientService::getCallbackArg(char *)' is private
CLIPService.cc:205: within this context
CLIPService.cc:205: in base initialization for class `cdevCallback'
compile done\n
=> g++ -c CLIPRequestObject.cc -o CLIPRequestObject.o
target is .shobj/Linux/CLIPRequestObject.o and CLIPRequestObject.cc
/home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/fifo.h: In function `static class QueueBase::node * QueueBase::newNode()':
In file included from /home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/ServerHandler.h:17,
from /home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/ServerInterface.h:5,
from /home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/cdevClientService.h:7,
from CLIPService.h:1,
from CLIPRequestObject.cc:2:
/home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/fifo.h:76: warning: ANSI C++ forbids implicit conversion from `void *' in assignment
/home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/StringHash.h: In method `char * StringHashIterator::key()':
In file included from /home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/ServerInterface.h:7,
from /home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/cdevClientService.h:7,
from CLIPService.h:1,
from CLIPRequestObject.cc:2:
/home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/StringHash.h:227: warning: ANSI C++ forbids implicit conversion from `void *' in return
/home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/ServerInterface.h: In method `class ServerHandler * ServerConnectionList::operator [](int)':
In file included from /home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/cdevClientService.h:7,
from CLIPService.h:1,
from CLIPRequestObject.cc:2:
/home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/ServerInterface.h:30: warning: ANSI C++ forbids implicit conversion from `void *' in return
/home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/cdevContextMap.h: In method `class cdevData * cdevContextMap::find(int)':
In file included from /home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/cdevClientService.h:9,
from CLIPService.h:1,
from CLIPRequestObject.cc:2:
/home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/cdevContextMap.h:28: warning: ANSI C++ forbids implicit conversion from `void *' in return
CLIPRequestObject.cc: In method `int CLIPRequestObject::getServerHandler(class ServerHandler **)':
CLIPRequestObject.cc:30: member `server' is private
CLIPRequestObject.cc:30: member `DDL_server' is private
CLIPRequestObject.cc:30: member `server' is private
CLIPRequestObject.cc:30: member `DDL_server' is private
CLIPRequestObject.cc:31: member `server' is private
CLIPRequestObject.cc:31: member `handler' is private
CLIPRequestObject.cc:33: member `server' is private
CLIPRequestObject.cc:38: member `handler' is private
CLIPRequestObject.cc:39: member `handler' is private
CLIPRequestObject.cc:42: member `handler' is private
compile done\n
start so build...
=> Building shared object CLIPService.so
/bin/sh: @@echo: command not found
gcc: .shobj/Linux/CLIPService.o: No such file or directory
gcc: .shobj/Linux/CLIPRequestObject.o: No such file or directory
make: *** [/home/pss060/sls/watson/1.7/extensions/cdevGenericServer/lib/Linux/CLIPService.so] Error 1
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 948 B

+948
View File
@@ -0,0 +1,948 @@
<! This document generated using mif2html Version 1.0 - Walt Akers - 1996 !>
<head>
<title>CDEV Script Service</title>
</head>
<body bgcolor="#E0E0FF">
<body>
<! ************************ FILE : cdevScriptServiceTITLE.mif *****************************!>
<br><hr><br>
<table width=100%>
<tr><td>
<! ***** Empty Column ***** !>
</td>
<td valign=top>
<!*** Start ADDRESS-VERSION ***!><font size=+2 color=Black>
CDEV Script Service
</p>
</p>
A Tool for Using Interactive Scripts from CDEV
</p>
</p>
Walt Akers
</p>
</p>
Version 1.0 February 11, 1997
</p>
</p>
TJNAF - Thomas Jefferson National Accelerator Facility
</p>
<!*** Finish ADDRESS-VERSION ***!></p></font>
</td></tr>
</table>
<! *************************** TABLE OF CONTENTS ****************************!>
<br><hr><br>
<table width=100%>
<tr><td>
<! ***** Empty Column ***** !>
</td>
<td valign=top align=center>
<!*** Start CLASS-TOC-TITLE ***!><font size=+3><strong>
Table of Contents
<!*** Finish CLASS-TOC-TITLE ***!></p></strong></font>
</td></tr>
<tr><td>
<! ***** Empty Column ***** !>
</td>
<td valign=top>
<table>
<tr><td valign=top align=right>
<!*** Start HEADING1TOC ***!><font size=+1 color=Black>
1.
<!*** Finish HEADING1TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start HEADING1TOC ***!><font size=+1 color=Black>
<a href="cdevScriptService.html#TOCREF1">Script Service Fundamentals</a>
<!*** Finish HEADING1TOC ***!><br></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<!*** Finish UHEADING2TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<a href="cdevScriptService.html#TOCREF2">Overview of the Script Service</a>
<!*** Finish UHEADING2TOC ***!><br></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<!*** Finish UHEADING2TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<a href="cdevScriptService.html#TOCREF3">Features of the Script Service</a>
<!*** Finish UHEADING2TOC ***!><br></font>
</td></tr>
<tr><td valign=top align=right>
<!*** Start HEADING1TOC ***!><font size=+1 color=Black>
2.
<!*** Finish HEADING1TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start HEADING1TOC ***!><font size=+1 color=Black>
<a href="cdevScriptService.html#TOCREF4">Building the Script Service</a>
<!*** Finish HEADING1TOC ***!><br></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<!*** Finish UHEADING2TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<a href="cdevScriptService.html#TOCREF5">Location of Files</a>
<!*** Finish UHEADING2TOC ***!><br></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<!*** Finish UHEADING2TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<a href="cdevScriptService.html#TOCREF6">Steps to Building Service</a>
<!*** Finish UHEADING2TOC ***!><br></font>
</td></tr>
<tr><td valign=top align=right>
<!*** Start HEADING1TOC ***!><font size=+1 color=Black>
3.
<!*** Finish HEADING1TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start HEADING1TOC ***!><font size=+1 color=Black>
<a href="cdevScriptService.html#TOCREF7">Structure of Data Provided to the Script</a>
<!*** Finish HEADING1TOC ***!><br></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<!*** Finish UHEADING2TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<a href="cdevScriptService.html#TOCREF8">General Form of Data String</a>
<!*** Finish UHEADING2TOC ***!><br></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<!*** Finish UHEADING2TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<a href="cdevScriptService.html#TOCREF9">Representation of Scalar Data</a>
<!*** Finish UHEADING2TOC ***!><br></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<!*** Finish UHEADING2TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<a href="cdevScriptService.html#TOCREF10">Representation of Array Data</a>
<!*** Finish UHEADING2TOC ***!><br></font>
</td></tr>
<tr><td valign=top align=right>
<!*** Start HEADING1TOC ***!><font size=+1 color=Black>
4.
<!*** Finish HEADING1TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start HEADING1TOC ***!><font size=+1 color=Black>
<a href="cdevScriptService.html#TOCREF11">Structure of Data Returned from the Script</a>
<!*** Finish HEADING1TOC ***!><br></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<!*** Finish UHEADING2TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<a href="cdevScriptService.html#TOCREF12">Returning Data to the Calling CDEV Application</a>
<!*** Finish UHEADING2TOC ***!><br></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<!*** Finish UHEADING2TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<a href="cdevScriptService.html#TOCREF13">General Form of String Data </a>
<!*** Finish UHEADING2TOC ***!><br></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<!*** Finish UHEADING2TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<a href="cdevScriptService.html#TOCREF14">Returning a Single Result Packet </a>
<!*** Finish UHEADING2TOC ***!><br></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<!*** Finish UHEADING2TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<a href="cdevScriptService.html#TOCREF15">Returning Multiple Result Packets </a>
<!*** Finish UHEADING2TOC ***!><br></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<!*** Finish UHEADING2TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<a href="cdevScriptService.html#TOCREF16">Special Considerations</a>
<!*** Finish UHEADING2TOC ***!><br></font>
</td></tr>
<tr><td valign=top align=right>
<!*** Start HEADING1TOC ***!><font size=+1 color=Black>
5.
<!*** Finish HEADING1TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start HEADING1TOC ***!><font size=+1 color=Black>
<a href="cdevScriptService.html#TOCREF17">DDL Entries for the Script Service</a>
<!*** Finish HEADING1TOC ***!><br></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<!*** Finish UHEADING2TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<a href="cdevScriptService.html#TOCREF18">Setting Up the DDL </a>
<!*** Finish UHEADING2TOC ***!><br></font>
</td></tr>
</table>
</td></tr>
</table>
<! **************************** LIST OF FIGURES *****************************!>
<br><hr><br>
<table width=100%>
<tr><td>
<! ***** Empty Column ***** !>
</td>
<td valign=top align=center>
<!*** Start CLASS-LOF-TITLE ***!><font size=+3><strong>
List of Figures
<!*** Finish CLASS-LOF-TITLE ***!></p></strong></font>
</td></tr>
<tr><td>
<! ***** Empty Column ***** !>
</td>
<td valign=top>
<!*** Start FIGURELOF ***!><font size=+1 color=Black>
Figure 7:
<a href="cdevScriptService.html#LOFREF1">General form of string representation of cdevData</a>
<!*** Finish FIGURELOF ***!><br></font>
<!*** Start FIGURELOF ***!><font size=+1 color=Black>
Figure 8:
<a href="cdevScriptService.html#LOFREF2">String representation of scalar data in a cdevData object</a>
<!*** Finish FIGURELOF ***!><br></font>
<!*** Start FIGURELOF ***!><font size=+1 color=Black>
Figure 9:
<a href="cdevScriptService.html#LOFREF3">String representation of array data</a>
<!*** Finish FIGURELOF ***!><br></font>
<!*** Start FIGURELOF ***!><font size=+1 color=Black>
Figure 10:
<a href="cdevScriptService.html#LOFREF4">Returning a single result packet to the CDEV application</a>
<!*** Finish FIGURELOF ***!><br></font>
<!*** Start FIGURELOF ***!><font size=+1 color=Black>
Figure 11:
<a href="cdevScriptService.html#LOFREF5">Returning a multiple result packets to the CDEV application</a>
<!*** Finish FIGURELOF ***!><br></font>
<!*** Start FIGURELOF ***!><font size=+1 color=Black>
Figure 12:
<a href="cdevScriptService.html#LOFREF6">Simple DDL file for the Script Service</a>
<!*** Finish FIGURELOF ***!><br></font>
</td></tr>
</table>
<! ************************ FILE : ./cdevScriptService.mif *****************************!>
<br><hr><br>
<table width=100%>
<tr><td valign=top align=right>
<!*** Start HEADING1 ***!><font size=+3 color=Black><strong>
1.
<!*** Finish HEADING1 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start HEADING1 ***!><font size=+3 color=Black><strong>
<a name="TOCREF1">
Script Service Fundamentals
</a> <!*** Finish HEADING1 ***!></p></strong></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2 ***!><font size=+1 color=Black><strong>
<a name="TOCREF2">
Overview of the
Script Service
</a> <!*** Finish UHEADING2 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start BODY ***!><font size=+1 color=Black>
The CDEV Script Service is designed to allow a a CDEV application to execute an
external script to process a message. The output that is produced by the executable
will be returned to the caller in the form of a cdevData. The CDEV Script Service
meets the following requirements.
<!*** Finish BODY ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2 ***!><font size=+1 color=Black><strong>
<a name="TOCREF3">
Features of the
Script Service
</a> <!*** Finish UHEADING2 ***!></p></strong></font>
</td>
<td valign=top>
<table>
<tr><td valign=top>
<!*** Start BULLETED ***!><font size=+1 color=Black>
<img src="bullet.jpg">
<!*** Finish BULLETED ***!></p></font>
</td>
<td valign=top>
<!*** Start BULLETED ***!><font size=+1 color=Black>
The filename of the script is associated with a CDEV device/message
combination by using the &quot;filename&quot; field of the class-data in the CDEV DDL file.
Syntax is described later in this document.
<!*** Finish BULLETED ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start BULLETED ***!><font size=+1 color=Black>
<img src="bullet.jpg">
<!*** Finish BULLETED ***!></p></font>
</td>
<td valign=top>
<!*** Start BULLETED ***!><font size=+1 color=Black>
A new process will be spawned for the script each time it is executed. Its standard
output (stdout) file descriptor will be redirected to return data to the main CDEV
application, allowing the script to return results to the parent process.
<!*** Finish BULLETED ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start BULLETED ***!><font size=+1 color=Black>
<img src="bullet.jpg">
<!*** Finish BULLETED ***!></p></font>
</td>
<td valign=top>
<!*** Start BULLETED ***!><font size=+1 color=Black>
The external executable file can be any form of user shell, batch file or binary
application that is supported on the host platform.
<!*** Finish BULLETED ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start BULLETED ***!><font size=+1 color=Black>
<img src="bullet.jpg">
<!*** Finish BULLETED ***!></p></font>
</td>
<td valign=top>
<!*** Start BULLETED ***!><font size=+1 color=Black>
The Script Service supports all of CDEV's send mechanisms; &quot;send&quot;,
&quot;sendNoBlock&quot; and &quot;sendCallback&quot;. Because of limits imposed on the number of
active processes, the user is advised to use the synchronous &quot;send&quot; method
whenever practical.
<!*** Finish BULLETED ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start BULLETED ***!><font size=+1 color=Black>
<img src="bullet.jpg">
<!*** Finish BULLETED ***!></p></font>
</td>
<td valign=top>
<!*** Start BULLETED ***!><font size=+1 color=Black>
When called by CDEV, the script will receive three arguments; the name of the
CDEV device associated with the request, the message string that was submitted
to the device, and a string that describes the contents of the outbound cdevData
object.
<!*** Finish BULLETED ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start BULLETED ***!><font size=+1 color=Black>
<img src="bullet.jpg">
<!*** Finish BULLETED ***!></p></font>
</td>
<td valign=top>
<!*** Start BULLETED ***!><font size=+1 color=Black>
The reply that is written to the standard output by the script must have a specific
format as described later in this document. A script may return more than one
reply packet to the caller.
<!*** Finish BULLETED ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start BULLETED ***!><font size=+1 color=Black>
<img src="bullet.jpg">
<!*** Finish BULLETED ***!></p></font>
</td>
<td valign=top>
<!*** Start BULLETED ***!><font size=+1 color=Black>
The script notifies CDEV that it has written its last reply packet by writing &quot;done&quot;
alone on a line to the standard output.
<!*** Finish BULLETED ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start BULLETED ***!><font size=+1 color=Black>
<img src="bullet.jpg">
<!*** Finish BULLETED ***!></p></font>
</td>
<td valign=top>
<!*** Start BULLETED ***!><font size=+1 color=Black>
If the script is to return multiple results, it should write &quot;end&quot; alone on a line to the
standard output between each packet, and write &quot;done&quot; alone on a line following
the last packet.
<!*** Finish BULLETED ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start BULLETED ***!><font size=+1 color=Black>
<img src="bullet.jpg">
<!*** Finish BULLETED ***!></p></font>
</td>
<td valign=top>
<!*** Start BULLETED ***!><font size=+1 color=Black>
If the script returns a value in the &quot;status&quot; tag of its reply packet, this will be
provided to the caller as the completion code of the message. Traditionally a
status of 0 indicates success, and all other values indicated an error occurred.
<!*** Finish BULLETED ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start BULLETED ***!><font size=+1 color=Black>
<img src="bullet.jpg">
<!*** Finish BULLETED ***!></p></font>
</td>
<td valign=top>
<!*** Start BULLETED ***!><font size=+1 color=Black>
Because the callback mechanism of the Script Service is triggered by output from
the script, the script developer should at least write &quot;done&quot; to the standard output
even if the application returns no output.
<!*** Finish BULLETED ***!></p></font>
</td></tr>
</table>
</td></tr>
<tr><td valign=top align=right>
<!*** Start HEADING1 ***!><font size=+3 color=Black><strong>
2.
<!*** Finish HEADING1 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start HEADING1 ***!><font size=+3 color=Black><strong>
<a name="TOCREF4">
Building the Script Service
</a> <!*** Finish HEADING1 ***!></p></strong></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2 ***!><font size=+1 color=Black><strong>
<a name="TOCREF5">
Location of Files
</a> <!*** Finish UHEADING2 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start BODY ***!><font size=+1 color=Black>
The source code for the Script Service is provided with the CDEV distribution starting
with version 1.5. The source code is located in the directory $CDEV/extensions/
ScriptService. The following steps should be taken to build the ScriptService.
<!*** Finish BODY ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2 ***!><font size=+1 color=Black><strong>
<a name="TOCREF6">
Steps to Building
Service
</a> <!*** Finish UHEADING2 ***!></p></strong></font>
</td>
<td valign=top>
<table>
<tr><td valign=top>
<!*** Start NUMBERED ***!><font size=+1 color=Black>
1.
<!*** Finish NUMBERED ***!></p></font>
</td>
<td valign=top>
<!*** Start NUMBERED ***!><font size=+1 color=Black>
Obtain and install the CDEV distribution - Version 1.5 or higher.
<!*** Finish NUMBERED ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start NUMBERED ***!><font size=+1 color=Black>
2.
<!*** Finish NUMBERED ***!></p></font>
</td>
<td valign=top>
<!*** Start NUMBERED ***!><font size=+1 color=Black>
Follow the installation steps to build CDEV on your system. This includes setting
all of the environment variables required by CDEV.
<!*** Finish NUMBERED ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start NUMBERED ***!><font size=+1 color=Black>
3.
<!*** Finish NUMBERED ***!></p></font>
</td>
<td valign=top>
<!*** Start NUMBERED ***!><font size=+1 color=Black>
Change directories to <em>$CDEV/extensions/ScriptService/src</em>.
<!*** Finish NUMBERED ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start NUMBERED ***!><font size=+1 color=Black>
4.
<!*** Finish NUMBERED ***!></p></font>
</td>
<td valign=top>
<!*** Start NUMBERED ***!><font size=+1 color=Black>
There is a collection of platform specific makefiles in the directory <em>$CDEV/
extensions/cdevGenericServer/include/makeinclude</em>. Link the makefile that is
appropriate to your architecture to the file Makefile.OS.
<!*** Finish NUMBERED ***!></p></font>
<!*** Start INDENTED ***!><font size=+1 color=Black>
For example, to link to the makefile for HP-UX, you would type the following
command.
</p>
</p>
<em>ln -s Makefile.hpux Makefile.OS</em>
</p>
<!*** Finish INDENTED ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start NUMBERED ***!><font size=+1 color=Black>
5.
<!*** Finish NUMBERED ***!></p></font>
</td>
<td valign=top>
<!*** Start NUMBERED ***!><font size=+1 color=Black>
Type make to compile and link the Script Service shared object. Note that you
must be using GNU make in order to build this distribution.
<!*** Finish NUMBERED ***!></p></font>
</td></tr>
</table>
<!*** Start BODY ***!><font size=+1 color=Black>
Upon completion the Makefile will generate the shared object for the Script Service
and will install it into your CDEVSHOBJ directory. At this point you are ready to use
the Script Service.
<!*** Finish BODY ***!></p></font>
</td></tr>
<tr><td valign=top align=right>
<!*** Start HEADING1 ***!><font size=+3 color=Black><strong>
3.
<!*** Finish HEADING1 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start HEADING1 ***!><font size=+3 color=Black><strong>
<a name="TOCREF7">
Structure of Data Provided to the Script
</a> <!*** Finish HEADING1 ***!></p></strong></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2 ***!><font size=+1 color=Black><strong>
<a name="TOCREF8">
General Form of
Data String
</a> <!*** Finish UHEADING2 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start BODY ***!><font size=+1 color=Black>
When a developer makes a CDEV send call, he may provide outbound data in the
form of a cdevData object. Before calling the script, this data is converted into a string
and provided as the third argument to the application (the first argument is the device
name and the second is the message). The structure of the outbound data string is of
the following form.
</p>
<!*** Finish BODY ***!></p></font>
<!*** Start FIGURE ***!><font size=+0 color=Black><em>
Figure 7:
<a name="LOFREF1">
General form of string representation of cdevData
<table border=1><tr><td>
<table>
<tr><td>
<! ***** Empty Column ***** !>
</td>
<td valign=top>
<!*** Start PROGRAM ***!><pre><font size=+0 color=Black><strong><em>
tag1=&quot;string value&quot;
tag2=1.00
<!*** Finish PROGRAM ***!></strong></em></font></pre>
</td></tr>
</table>
</tr></td></table>
<AFrame 13>
</a> <!*** Finish FIGURE ***!></p></em></font>
<!*** Start BODY ***!><font size=+1 color=Black>
<!*** Finish BODY ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2 ***!><font size=+1 color=Black><strong>
<a name="TOCREF9">
Representation of
Scalar Data
</a> <!*** Finish UHEADING2 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start BODY ***!><font size=+1 color=Black>
The above example shows two data entries of the form <em>tag=value</em>. Each entry is
separated by a carriage return. The first entry has a tag name of <em>'tag1'</em> and a value of
<em>'string value'</em>. You will note that <em>'string value'</em> is enclosed in double quotes in the
example. This is used to notify the script that the value is a non-numeric character
string. In the second data entry the value <em>'1.0' </em>is not enclosed in quotes, indicating that
the value is a number.
</p>
The following example illustrates how scalar values stored in a cdevData object would
look when they are passed to the script.
</p>
<!*** Finish BODY ***!></p></font>
<!*** Start FIGURE ***!><font size=+0 color=Black><em>
Figure 8:
<a name="LOFREF2">
String representation of scalar data in a cdevData object
<table border=1><tr><td>
<table>
<tr><td>
<! ***** Empty Column ***** !>
</td>
<td valign=top>
<!*** Start PROGRAM ***!><pre><font size=+0 color=Black><strong><em>
Data stored in cdevData object:
Tag: value
Data Type: character string
Value: Test
Tag: status
Data Type: integer
Value: 0
Tag: controlHigh
Data Type: double
Value: 1.001
String representation provided to script:
value=&quot;Test&quot;\\n
status=0\\n
controlHigh=1.001\\n
<!*** Finish PROGRAM ***!></strong></em></font></pre>
</td></tr>
</table>
</tr></td></table>
<AFrame 1>
</a> <!*** Finish FIGURE ***!></p></em></font>
<!*** Start BODY ***!><font size=+1 color=Black>
<!*** Finish BODY ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2 ***!><font size=+1 color=Black><strong>
<a name="TOCREF10">
Representation of
Array Data
</a> <!*** Finish UHEADING2 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start BODY ***!><font size=+1 color=Black>
If array data is stored in the outbound cdevData object, it too can be provided to the
script. The data is structured in the standard C format where opening and closing
braces mark the beginning and end (respectively) of each array bound. The following
example illustrates how various arrays would be represented as strings.
<!*** Finish BODY ***!></p></font>
<!*** Start FIGURE ***!><font size=+0 color=Black><em>
Figure 9:
<a name="LOFREF3">
String representation of array data
<table border=1><tr><td>
<table>
<tr><td>
<! ***** Empty Column ***** !>
</td>
<td valign=top>
<!*** Start PROGRAM ***!><pre><font size=+0 color=Black><strong><em>
Data stored in cdevData object:
Tag: value
Data Type: character string [3]
Value: &quot;value1&quot; &quot;value2&quot; &quot;value3&quot;
String representation provided to script:
value={&quot;value1&quot;,&quot;value2&quot;,&quot;value3&quot;}\\n
<AFrame 5>
Data stored in cdevData object:
Tag: value
Data Type: double [3]
Value: 1.0, 2.0, 3.01
String representation provided to script:
value={1,2,3.01}\\n
<AFrame 6>
Data stored in cdevData object:
Tag: value
Data Type: double [3][2]
Value: 1.0, 2.0, 3.0, 4.0, 5.0, 6.0
String representation provided to script:
value={{1,2},{3,4},{5,6}}\\n
<!*** Finish PROGRAM ***!></strong></em></font></pre>
</td></tr>
</table>
</tr></td></table>
<AFrame 3>
</a> <!*** Finish FIGURE ***!></p></em></font>
</td></tr>
<tr><td valign=top align=right>
<!*** Start HEADING1 ***!><font size=+3 color=Black><strong>
4.
<!*** Finish HEADING1 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start HEADING1 ***!><font size=+3 color=Black><strong>
<a name="TOCREF11">
Structure of Data Returned from the Script
</a> <!*** Finish HEADING1 ***!></p></strong></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2 ***!><font size=+1 color=Black><strong>
<a name="TOCREF12">
Returning Data to
the Calling CDEV
Application
</a> <!*** Finish UHEADING2 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start BODY ***!><font size=+1 color=Black>
Before CDEV starts the script, it creates a pipe that is used to pass data between the
script and the CDEV application. One end of this pipe is maintained by the application
and the other end of the pipe is provided to the script as its standard output. This
means that anytime the script uses the &quot;echo&quot; command or the &quot;printf&quot; command, the
data that it output's will be transmitted through the pipe to the parent application.
</p>
The script is responsible for formatting the data into a collection of character strings
that can be recognized by the CDEV application.
<!*** Finish BODY ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2 ***!><font size=+1 color=Black><strong>
<a name="TOCREF13">
General Form of
String Data
</a> <!*** Finish UHEADING2 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start BODY ***!><font size=+1 color=Black>
In general, the data that is returned from a script is of the same form as described in
the preceding section, &quot;<em>Structure of Data Provided to the Script</em>&quot;. The most notable
difference is that the script must terminate the list by providing a character string that
indicates that the group of data items is complete; the string &quot;<em>end</em>&quot; or &quot;<em>done</em>&quot; alone on
a line.
<!*** Finish BODY ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2 ***!><font size=+1 color=Black><strong>
<a name="TOCREF14">
Returning a
Single Result
Packet
</a> <!*** Finish UHEADING2 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start BODY ***!><font size=+1 color=Black>
If the script is going to return exactly one result packet (<em>a group of tags and values that
will be used to populate the result cdevData</em>), then it should write the string &quot;<em>done</em>&quot; on
a line by itself immediately following the output data. This will notify the Script Service
that no more data will be returned from the script.
</p>
The following example shows how a single result will be returned from a script. Note
that the &quot;status&quot; tag contains the completion code that will be returned to the CDEV
application.
<!*** Finish BODY ***!></p></font>
<!*** Start FIGURE ***!><font size=+0 color=Black><em>
Figure 10:
<a name="LOFREF4">
Returning a single result packet to the CDEV application
<table border=1><tr><td>
<table>
<tr><td>
<! ***** Empty Column ***** !>
</td>
<td valign=top>
<!*** Start PROGRAM ***!><pre><font size=+0 color=Black><strong><em>
#\\! /bin/csh -f
echo value=\\&quot;Test\\&quot;
echo status=0
echo controlLow=1.5
echo controlHigh=25.1
echo done
<!*** Finish PROGRAM ***!></strong></em></font></pre>
</td></tr>
</table>
</tr></td></table>
<AFrame 7>
</a> <!*** Finish FIGURE ***!></p></em></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2 ***!><font size=+1 color=Black><strong>
<a name="TOCREF15">
Returning
Multiple Result
Packets
</a> <!*** Finish UHEADING2 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start BODY ***!><font size=+1 color=Black>
Returning multiple results from a single script execution is not generally advised.
However, If the script is going to return more than one result packet, then each interim
packet should be terminated by the &quot;<em>end</em>&quot; keyword on a line by itself. The &quot;<em>done</em>&quot;
keyword should follow the last entry.
</p>
The following example shows how two results will be returned from a script.
<!*** Finish BODY ***!></p></font>
<!*** Start FIGURE ***!><font size=+0 color=Black><em>
Figure 11:
<a name="LOFREF5">
Returning a multiple result packets to the CDEV application
<table border=1><tr><td>
<table>
<tr><td>
<! ***** Empty Column ***** !>
</td>
<td valign=top>
<!*** Start PROGRAM ***!><pre><font size=+0 color=Black><strong><em>
#\\! /bin/csh -f
echo value=\\&quot;Start Result 1\\&quot;
echo status=0
echo end
echo value=\\&quot;Start Result 2\\&quot;
echo status=-1
echo done
<!*** Finish PROGRAM ***!></strong></em></font></pre>
</td></tr>
</table>
</tr></td></table>
<AFrame 9>
</a> <!*** Finish FIGURE ***!></p></em></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2 ***!><font size=+1 color=Black><strong>
<a name="TOCREF16">
Special
Considerations
</a> <!*** Finish UHEADING2 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start BODY ***!><font size=+1 color=Black>
If the script that is being executed will not return a result, then the developer should
still write &quot;<em>done&quot;</em> to the standard output in order to notify the CDEV application that it
should no longer wait for output. If the script is not returning a result, it may write the
terminating <em>&quot;done&quot;</em> at the beginning of the script or at the end. Because synchronous
calls will block until a reply is received, the developer should return a result to the
CDEV application as quickly as possible.
</p>
If the developer never writes anything to the standard output, then the user specified
CDEV callback will never be executed... therefore, it is crucial to notify the CDEV
application when the script has completed.
<!*** Finish BODY ***!></p></font>
</td></tr>
<tr><td valign=top align=right>
<!*** Start HEADING1 ***!><font size=+3 color=Black><strong>
5.
<!*** Finish HEADING1 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start HEADING1 ***!><font size=+3 color=Black><strong>
<a name="TOCREF17">
DDL Entries for the Script Service
</a> <!*** Finish HEADING1 ***!></p></strong></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2 ***!><font size=+1 color=Black><strong>
<a name="TOCREF18">
Setting Up the
DDL
</a> <!*** Finish UHEADING2 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start BODY ***!><font size=+1 color=Black>
The following example illustrates how to add a service entry to identify the Script
Service and how to use the class-data to specify the filename that the Script Service
will execute to service a message.
<!*** Finish BODY ***!></p></font>
<!*** Start FIGURE ***!><font size=+0 color=Black><em>
Figure 12:
<a name="LOFREF6">
Simple DDL file for the Script Service
<table border=1><tr><td>
<table>
<tr><td>
<! ***** Empty Column ***** !>
</td>
<td valign=top>
<!*** Start PROGRAM ***!><pre><font size=+0 color=Black><strong><em>
/*
* This is the service definition, it tells CDEV that there is
* a service named Script and that it will use the cdevData
* tag 'filename' to read configuration information from the
* DDL file entries.
*/
service Script
{
tags {filename}
}
/*
* This class definition identifies the class scriptClass which
* supports the &quot;get and &quot;set&quot; commands on attributes &quot;attrib0&quot;
* and &quot;attrib1&quot;. Note that attrib0 will call script /bin/ouch
* and attrib1 will call script /bin/wammo.
*/
class scriptClass
{
verbs {get, set}
attributes
{
attrib0 Script {filename = /bin/ouch};
attrib1 Script {filename = /bin/wammo};
}
}
/*
* Finally, the CDEV DDL identifies two devices that are of type
* scriptClass. Any time one of the supported messages is passed
* to one of these devices it will activate the corresponding
* script.
*/
scriptClass : device0, device1;
<!*** Finish PROGRAM ***!></strong></em></font></pre>
</td></tr>
</table>
</tr></td></table>
<AFrame 11>
</a> <!*** Finish FIGURE ***!></p></em></font>
<!*** Start BODY ***!><font size=+1 color=Black>
<!*** Finish BODY ***!></p></font>
</td></tr>
</table>
</body>
+21
View File
@@ -0,0 +1,21 @@
#! /bin/csh
if( -f fmbatch.dat) rm fmbatch.dat
if( -d html) rm -rf html
mkdir -p html
cp $CDEV/doc/bullet.jpg html
foreach x (`find . -name \*.doc -a ! -name \*TOC.doc -a ! -name \*LOF.doc`)
echo "Open $x" >> fmbatch.dat
echo "SaveAs ma $x html/`basename $x .doc`.mif" >> fmbatch.dat
end
fmbatch fmbatch.dat
cd html
foreach x (`find . -name \*.mif -a ! -name \*TITLE.mif`)
mif2html -t 'CDEV Script Service' -o `basename $x .mif`.html `basename $x .mif`TITLE.mif \-TOC \-LOF $x
end
rm *.mif
+46
View File
@@ -0,0 +1,46 @@
ARCH = OS
SHOBJ = YES
include $(CDEV)/extensions/cdevGenericServer/include/makeinclude/Makefile.$(ARCH)
APPNAME = "CDEV/ACE Script Service"
CXXINCLUDES = -I./
BASEBIN = ./
SO_LIBS = $(OSLIBS)
SO_SRCS = ScriptService.cc \
ScriptRequestObject.cc \
ScriptList.cc
OBJS = $(OBJDIR)/ScriptService.o \
$(OBJDIR)/ScriptRequestObject.o \
$(OBJDIR)/ScriptList.o
# ******************************************************************************
# * The BINARIES definition names all of the binary files that should be deleted
# * whenever "make clean" is executed.
# ******************************************************************************
BINARIES = $(CDEVLIB)/libScriptService.a \
$(CDEVSHOBJ)/$(CDEVVERSION)/ScriptService.so
ifeq ($(SHOBJ), YES)
LIBS = $(CDEVLIBS) $(OSLIBS)
TARGETS = $(CDEVSHOBJ)/$(CDEVVERSION)/ScriptService.so
else
LIBS = $(CDEVLIBS) -lScriptService $(OSLIBS)
TARGETS = $(CDEVLIB)/libScriptService.a
endif
targets : $(TARGETS)
$(CDEVSHOBJ)/$(CDEVVERSION)/ScriptService.so : $(OBJS)
@rm -f $@
@$(SOBUILD)
@mkdir -p $(CDEVSHOBJ)/$(CDEVVERSION)
@echo "<= Done...\n"
$(CDEVLIB)/libScriptService.a : $(OBJS)
@rm -f $@
@echo "=> Building archive library $(@F)"
@echo " => Linking $(@F) from objects"
@$(LINK.a) $@ $^
@$(RANLIB) $@ > /dev/null
@echo "<= Done...\n"
+958
View File
@@ -0,0 +1,958 @@
// -----------------------------------------------------------------------------
// 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 script service.
//
// Author: Walt Akers
//
// Revision History:
// ScriptList.cc,v
// Revision 1.3 1997/02/14 20:43:40 akers
// Ongoing improvement
//
// Revision 1.2 1997/02/14 20:06:32 akers
// Ongoing improvement
//
// Revision 1.1 1997/02/11 17:37:22 akers
// Directory restructure
//
// Revision 1.7 1997/02/10 20:31:23 akers
// Ongoing improvement
//
// Revision 1.6 1997/02/07 16:19:43 akers
// Ongoing development
//
// Revision 1.5 1997/02/06 20:27:48 akers
// Ongoing development
//
// Revision 1.4 1997/01/31 21:09:58 akers
// Ongoing Development
//
// Revision 1.3 1997/01/31 18:51:26 akers
// Ongoing development
//
// Revision 1.2 1997/01/31 16:21:22 akers
// Ongoing development
//
// Revision 1.1 1997/01/30 20:35:33 akers
// Initial installation of Script Service
//
// -----------------------------------------------------------------------------
#include <ScriptList.h>
// *****************************************************************************
// * ScriptData::ScriptData :
// * Constructor for the class...
// *****************************************************************************
ScriptData::ScriptData ( cdevTranObj & Xobj )
: next(NULL), data(new cdevData),
xobj(&Xobj), inputBuf(NULL),
inputBufLen(0), amntRead(0),
process(0), finished(0), callbackCount(0)
{
// *********************************************************************
// * Attempt to create the pipe that will be used to return
// * the result to the class.
// *********************************************************************
if(pipe((int *)&sp)!=0)
{
sp.readFD = -1;
sp.writeFD = -1;
}
}
// *****************************************************************************
// * ScriptData::data2Buffer :
// * This method is used to convert a cdevData object into a
// * series of strings that can be used by the script.
// *****************************************************************************
int ScriptData::data2Buffer ( cdevData & data, char *& buf, int &bufLen)
{
cdevDataIterator iter(&data);
int i;
int idx = 0;
struct DataPack
{
char * tag;
char ** ptr;
double * dPtr;
size_t ptrCnt;
int quoted;
cdevBounds * bounds;
size_t boundsCnt;
} dataPack[256];
memset(dataPack, 0, sizeof(dataPack));
// *********************************************************************
// * Iterate through the cdevData object and collect the data
// * that is stored into an array of character strings.
// *********************************************************************
for(bufLen=0, iter.init(); !iter && idx<256; idx++)
{
// *************************************************************
// * Get the tag string and add the length of that plus
// * the length of a seperating equals sign (=) to the
// * buffer length.
// *************************************************************
data.tagI2C(iter.tag(), dataPack[idx].tag);
bufLen+=strlen(dataPack[idx].tag)+2;
// *************************************************************
// * Get the number of elements in the array.
// *************************************************************
data.getElems(dataPack[idx].tag, &dataPack[idx].ptrCnt);
// *************************************************************
// * If the data object is a string, add two times the
// * number of elements to the buffer length (to account
// * for double quotes around each entry.)
// *************************************************************
if(data.getType(dataPack[idx].tag)==CDEV_STRING ||
data.getType(dataPack[idx].tag)==CDEV_TIMESTAMP)
{
dataPack[idx].quoted = 1;
bufLen+=(2*dataPack[idx].ptrCnt);
// *****************************************************
// * Allocate an array of character strings to
// * be used to extract the array as a
// * collection of strings and increase the
// * buffer length to accomodate all of the
// * items.
// *****************************************************
dataPack[idx].ptr = new char * [dataPack[idx].ptrCnt];
data.get(dataPack[idx].tag, dataPack[idx].ptr);
for(i=0; i<dataPack[idx].ptrCnt; i++)
{
bufLen+=strlen(dataPack[idx].ptr[i]);
}
}
else
{
// *****************************************************
// * Allocate an array of doubles to
// * be used to extract the array as a
// * collection and increase the buffer length
// * to accomodate all of the items.
// *****************************************************
dataPack[idx].dPtr = new double [dataPack[idx].ptrCnt];
data.get(dataPack[idx].tag, dataPack[idx].dPtr);
bufLen += 21*dataPack[idx].ptrCnt;
}
// *************************************************************
// * Add 1 character for each entry to account for
// * commas between entries.
// *************************************************************
bufLen += dataPack[idx].ptrCnt;
// *************************************************************
// * Get the number of dimensions in the tagged data
// * item.
// *************************************************************
data.getDim(dataPack[idx].tag, &dataPack[idx].boundsCnt);
// *************************************************************
// * If the data is an array or vector, then calculate
// * the amount of space that will have to be used
// * to store the separating brace characters (and commas).
// *************************************************************
if(dataPack[idx].boundsCnt!=0)
{
int braceCount = 1;
dataPack[idx].bounds = new cdevBounds[dataPack[idx].boundsCnt];
data.getBounds(dataPack[idx].tag, dataPack[idx].bounds, dataPack[idx].boundsCnt);
for(i=0; i<dataPack[idx].boundsCnt-1; i++)
{
if(i==0) braceCount +=
dataPack[idx].bounds[i].length;
else braceCount +=
dataPack[idx].bounds[i-1].length*
dataPack[idx].bounds[i].length;
}
bufLen += braceCount*3;
}
// *************************************************************
// * Add space for the separating carriage return.
// *************************************************************
bufLen+=1;
// *************************************************************
// * Move to the next item in the list.
// *************************************************************
++iter;
}
// *********************************************************************
// * Allocate a buffer of sufficient size to hold the result
// * plus a NULL terminating character and an opening and closing
// * single quote.
// *********************************************************************
if(idx) {
buf = new char [bufLen+1+2];
*buf = 0;
}
else {
buf = NULL;
bufLen = 0;
}
// *********************************************************************
// * Walk through each item in the list and place it in the
// * data buffer.
// *********************************************************************
int max = idx;
for(idx=0; idx<max; idx++)
{
char * ptr = buf+strlen(buf);
sprintf(ptr, "%s=", dataPack[idx].tag);
if(!dataPack[idx].boundsCnt)
{
if(dataPack[idx].quoted)
sprintf(ptr+strlen(ptr), "\"%s\"\n", dataPack[idx].ptr[0]);
else sprintf(ptr+strlen(ptr), "%g\n", dataPack[idx].dPtr[0]);
}
else {
size_t ptrIdx = 0;
strcat(ptr, "{");
if(dataPack[idx].quoted)
{
dataArray2Buffer(ptr+strlen(ptr),
dataPack[idx].ptr,
ptrIdx,
dataPack[idx].bounds,
dataPack[idx].boundsCnt,
0);
}
else
{
dataArray2Buffer(ptr+strlen(ptr),
dataPack[idx].dPtr,
ptrIdx,
dataPack[idx].bounds,
dataPack[idx].boundsCnt,
0);
}
strcat(ptr, "}\n");
}
// *************************************************************
// * Delete the allocated contents of the dataPack once
// * it is no longer needed.
// *************************************************************
if(dataPack[idx].quoted)
{
for(int j=0; j<dataPack[idx].ptrCnt; j++)
{
delete dataPack[idx].ptr[j];
}
delete dataPack[idx].ptr;
}
else delete dataPack[idx].dPtr;
delete dataPack[idx].bounds;
}
return CDEV_SUCCESS;
}
// *****************************************************************************
// * ScriptList::dataArray2Buffer :
// * This is a method that is called recursively to dump the contents
// * of a string array to the buffer.
// *****************************************************************************
void ScriptData::dataArray2Buffer (char * output,
char ** ptr,
size_t & ptrIdx,
cdevBounds * bounds,
size_t nBounds,
size_t boundsIdx)
{
for(int i=0; i<bounds[boundsIdx].length; i++)
{
if(boundsIdx<nBounds-1)
{
strcat(output, "{");
dataArray2Buffer(output+strlen(output), ptr, ptrIdx, bounds, nBounds, boundsIdx+1);
if(i+1<bounds[boundsIdx].length) strcat(output, "},");
else strcat(output, "}");
}
else {
output+=strlen(output);
if(i+1<bounds[boundsIdx].length) sprintf(output, "\"%s\",", ptr[ptrIdx++]);
else sprintf(output, "\"%s\"", ptr[ptrIdx++]);
}
}
}
// *****************************************************************************
// * ScriptList::dataArray2Buffer :
// * This is a method that is called recursively to dump the contents
// * of a double array to the buffer.
// *****************************************************************************
void ScriptData::dataArray2Buffer (char * output,
double * ptr,
size_t & ptrIdx,
cdevBounds * bounds,
size_t nBounds,
size_t boundsIdx)
{
for(int i=0; i<bounds[boundsIdx].length; i++)
{
if(boundsIdx<nBounds-1)
{
strcat(output, "{");
dataArray2Buffer(output+strlen(output), ptr, ptrIdx, bounds, nBounds, boundsIdx+1);
if(i+1<bounds[boundsIdx].length) strcat(output, "},");
else strcat(output, "}");
}
else {
output+=strlen(output);
if(i+1<bounds[boundsIdx].length) sprintf(output, "%g,", ptr[ptrIdx++]);
else sprintf(output, "%g", ptr[ptrIdx++]);
}
}
}
// *****************************************************************************
// * ScriptData::buffer2Data :
// * This method allows the ScriptData class to read the inbound
// * results of the script inot a cdevData buffer.
// *
// * Each line of the result should be structured as such.
// *
// * Tag value\n
// *
// * All results are assumed to be doubles unless they are enclosed
// * in double quotes (").
// *
// * If an array of items is returned, it should be enclosed in
// * braces as described below.
// *
// * 1) Returning a string:
// *
// * value="Test"\n
// * status "Running very well"\n
// *
// * 2) Returning a double:
// * value=10.01\n
// * status=1\n
// *
// * 3) Returning an array of strings
// * value={"John","Jacob","Jingleheimer","Schmidt"}\n
// *
// * 4) Returning a two dimensional array of doubles: ie x[2][3]
// * value={{1.0,2.0,3.0}{4.0,5.0,6.0}}\n
// *
// *****************************************************************************
int ScriptData::buffer2Data ( char * &buf, cdevData & data )
{
int done = 0;
char * ptr = buf;
while(ptr && *ptr)
{
while(isspace(*ptr)) ptr++;
char * tag = ptr;
// *************************************************************
// * Find the end of the tag and remove any trailing
// * spaces that are associated with it.
// *************************************************************
if(*tag) ptr = strchr(ptr, '=');
// *************************************************************
// * If the pointer does not point to a valid line, jump to
// * the next line and continue from the top of the loop.
// *************************************************************
if(!ptr || !(*ptr))
{
ptr = strchr(ptr, '\n');
continue;
}
else {
char *temp = ptr-1;
*(ptr++) = 0;
while(isspace(*temp)) *(temp--)=0;
}
// *************************************************************
// * Find the beginning of the data.
// *************************************************************
while(*ptr && isspace(*ptr)) ptr++;
// *************************************************************
// * Beginning of an array of things.
// *************************************************************
if(*ptr=='{')
{
cdevDataTypes dataType = CDEV_DOUBLE;
char ** strData = NULL;
double * dblData = NULL;
char * tPtr = ptr;
cdevBounds * bounds;
int nDim = 0;
int dimIdx = 0;
int itmCnt = 0;
int itmIdx = 0;
int chkSum = 1;
// *****************************************************
// * Count the number of opening braces, this will
// * indicate the number of dimensions in the array.
// *****************************************************
while(*(tPtr++)=='{') nDim++;
bounds = new cdevBounds[nDim];
for(dimIdx=0; dimIdx<nDim; dimIdx++)
{
bounds[dimIdx].offset = 0;
bounds[dimIdx].length = 0;
}
// *****************************************************
// * Now count the number of the dimensions in the array
// *****************************************************
for(tPtr=ptr+1, dimIdx=0; dimIdx>=0 && *tPtr; tPtr++)
{
if(*tPtr=='"')
{
tPtr = strchr(tPtr+1, '"');
dataType = CDEV_STRING;
}
else if(*tPtr=='}')
{
if(dimIdx==nDim-1) bounds[dimIdx].length++;
dimIdx--;
}
else if(*tPtr=='{')
{
bounds[dimIdx++].length++;
}
else if(*tPtr==',' && dimIdx==nDim-1)
{
bounds[dimIdx].length++;
}
}
// *****************************************************
// * At this point, the last element of the bounds
// * array will contain the total count of items.
// *****************************************************
itmCnt = bounds[nDim-1].length;
// *****************************************************
// * To set each bounds element to its actual array
// * dimension, it will be necessary to divide it by
// * the size of its predecessor - working backwards.
// *****************************************************
for(dimIdx = nDim-2; dimIdx>=0; dimIdx--)
{
bounds[dimIdx+1].length /= bounds[dimIdx].length;
}
for(dimIdx = 0; dimIdx<nDim; dimIdx++)
{
chkSum*=bounds[dimIdx].length;
}
if(chkSum==itmCnt && chkSum>0)
{
// *****************************************************
// * Allocate a buffer of the correct type to hold the
// * data.
// *****************************************************
if(dataType == CDEV_STRING) strData = new char *[itmCnt];
else dblData = new double [itmCnt];
// *****************************************************
// * Walk through the data and accumulate the items
// * into the array.
// *****************************************************
tPtr = ptr;
dimIdx = -1;
do {
if(*tPtr=='{')
{
int jumpTheComma = 0;
dimIdx++;
tPtr++;
if(*tPtr && dimIdx==nDim-1) do
{
if(*tPtr==',' && jumpTheComma) tPtr++;
while(isspace(*tPtr)) tPtr++;
if(dataType==CDEV_DOUBLE)
{
dblData[itmIdx++] = atof(tPtr);
while(*tPtr && *tPtr!=',' && *tPtr!='}') tPtr++;
}
else {
char oldEndVal;
char * ePtr;
if(*tPtr=='"')
{
tPtr++;
ePtr = strchr(tPtr, '"');
}
else for(ePtr=tPtr; *ePtr && *ePtr!=',' && *ePtr!='}'; ePtr++);
if(ePtr)
{
oldEndVal = *ePtr;
*ePtr = 0;
}
strData[itmIdx++] = strdup(tPtr);
if(ePtr)
{
*ePtr = oldEndVal;
tPtr = (*ePtr=='"')?ePtr+1:ePtr;
}
else tPtr = tPtr+strlen(tPtr);
}
jumpTheComma = (*tPtr==',')?1:0;
} while(*tPtr!='}' && *tPtr);
}
else if(*tPtr=='}')
{
dimIdx--;
tPtr++;
}
else tPtr++;
} while (*tPtr && itmIdx<itmCnt && dimIdx>=0);
if(dataType==CDEV_STRING)
{
data.insert(tag, strData, itmCnt, nDim);
for(int x=0; x<itmCnt; x++) delete strData[x];
delete strData;
}
else {
data.insert(tag, dblData, itmCnt, nDim);
delete dblData;
}
data.setBounds(tag, bounds, nDim);
}
delete bounds;
for(ptr=tPtr; *ptr && *ptr!='\n'; ptr++);
}
// *************************************************************
// * Beginning of a string.
// *************************************************************
else if(*ptr=='"')
{
ptr++;
char * temp = ptr;
while(*temp!='"') temp++;
if(*temp=='"')
{
*(temp++)=0;
data.insert(tag, ptr);
}
for(ptr = temp; *ptr && *ptr!='\n'; ptr++);
}
// *************************************************************
// * Beginning of a double.
// *************************************************************
else if(*ptr)
{
data.insert(tag, atof(ptr));
while(*ptr && *ptr!='\n') ptr++;
}
}
return CDEV_SUCCESS;
}
// *****************************************************************************
// * ScriptData::fireCallback :
// * Deploys the callback associated with the class instance.
// *****************************************************************************
void ScriptData::fireCallback ( int result, void * arg, cdevRequestObject &req, cdevData & data, int partial)
{
// *********************************************************************
// * Fire the user provided callback and increment the counter.
// *********************************************************************
xobj->userCallback_->fireCallback ( result, arg, req, data, partial );
callbackCount++;
}
// *****************************************************************************
// * ScriptData::dispatch :
// * This method is responsible for collecting data from the
// * read file descriptor, and executing the callback associated
// * with it.
// *
// * This method will return the number of messages that it handled.
// *****************************************************************************
int ScriptData::dispatch ( void )
{
int nHandled = 0;
if(!finished)
{
int count = 0;
int stat_val;
// *************************************************************
// * Find out how many bytes are ready to read.
// *************************************************************
while(ioctl(sp.readFD, FIONREAD, &count)==0 && count>0)
{
// *****************************************************
// * If the input buffer has not already been
// * allocated, then allocate a new one that
// * is of sufficient size in increments of
// * 1024 bytes.
// *****************************************************
if(inputBufLen==0)
{
inputBufLen = (count/1024+1)*1024;
inputBuf = (char *)malloc(inputBufLen);
}
// *****************************************************
// * If the existing buffer is not sufficiently
// * large, then allocate a new one that is
// * of sufficient size in increments of
// * 1024 bytes.
// *********************************************
else if(amntRead + count > inputBufLen)
{
inputBufLen = ((amntRead+count)/1024+1)*1024;
inputBuf = (char *)realloc(inputBuf, inputBufLen);
}
// *****************************************************
// * Read the data that is ready into the buffer
// *****************************************************
amntRead += read(sp.readFD, inputBuf+amntRead, count);
// *****************************************************
// * NULL terminate the buffer to prevent memory
// * overruns while performing string operations
// *****************************************************
inputBuf[amntRead] = 0;
int done = 0;
// *****************************************************
// * Search the data for the "done" or "end" keywords
// * on a line by themselves... Either of these
// * keywords indicate the end of a data transmission.
// *****************************************************
do {
char * ePtr = NULL;
if (strncmp(inputBuf, "end\n", 4)==0 ||
strncmp(inputBuf, "done\n", 5)==0)
{
ePtr = inputBuf;
}
else if((ePtr = strstr(inputBuf, "\nend\n"))!=NULL ||
(ePtr = strstr(inputBuf, "\ndone\n"))!=NULL)
{
ePtr++;
}
else done = 1;
if(ePtr && *ePtr)
{
if(*ePtr=='d')
{
*ePtr = 0;
ePtr += 5;
finished = 1;
}
else {
*ePtr = 0;
ePtr += 4;
}
buffer2Data (inputBuf, *data);
strcpy(inputBuf, ePtr);
amntRead = strlen(inputBuf);
// *************************************
// * If no more data is ready,
// * determine if the process
// * is still alive.
// *************************************
stat_val = 0;
if(waitpid(process, &stat_val, WNOHANG)==process &&
(errno==ECHILD || WIFEXITED(stat_val)))
{
finished = 1;
}
// *************************************
// * Transfer the data from the
// * temporary data object into
// * the user-defined result
// * data object.
// *************************************
if(xobj->resultData_==NULL)
xobj->resultData_ = data;
else *(xobj->resultData_) = *data;
// *************************************
// * Fire the user provided
// * callback and increment the
// * callback counter. The status as
// * returned in the cdevData object
// * is the status for the request.
// *************************************
int status = CDEV_SUCCESS;
xobj->resultData_->get("status", &status);
fireCallback
(
status,
xobj->userCallback_->userarg(),
*xobj->reqObj_,
*xobj->resultData_,
!finished);
nHandled++;
}
} while(!done && !finished);
}
// *************************************************************
// * When no more data is ready, determine if the process is
// * still alive.
// *************************************************************
if(!finished && waitpid(process, &stat_val, WNOHANG)==process &&
(errno==ECHILD || WIFEXITED(stat_val)))
{
finished = 1;
}
}
return nHandled;
}
// *****************************************************************************
// * ScriptData::~ScriptData :
// * The destructor is protected to prevent it from being deleted by
// * anyone except the ScriptList class.
// *****************************************************************************
ScriptData::~ScriptData ( void )
{
static int killCount = 0;
if(callbackCount==0)
{
data->remove();
fireCallback (
CDEV_SUCCESS,
xobj->userCallback_->userarg(),
*xobj->reqObj_,
*data);
}
if(inputBuf) delete inputBuf;
if(sp.readFD != -1) close(sp.readFD);
if(sp.writeFD != -1) close(sp.writeFD);
if(data) delete data;
if(xobj)
{
xobj->removeFromGrps();
delete xobj;
}
}
// *****************************************************************************
// * ScriptList::ScriptList :
// * This is the constructor for the ScriptList class. It
// * initializes the internals of the class to 0.
// *****************************************************************************
ScriptList::ScriptList ( void ) : scripts(NULL), fdList(NULL), fdCount(0), fdMax(0)
{
};
// *****************************************************************************
// * ScriptList::ScriptList :
// * This method will walk through the list of ScriptData objects and
// * will delete each of them in sequence.
// *
// * Note that is no callbacks have been delivered for the specified
// * ScriptData object, it will deliver a single callback with
// * CDEV_ERROR as the status prior to terminating.
// *****************************************************************************
ScriptList::~ScriptList ( void )
{
ScriptData * curr;
while(scripts!=NULL)
{
curr = scripts;
scripts = scripts->next;
delete curr;
}
}
// *****************************************************************************
// * ScriptList::find :
// * This method allows the caller to locate the ScriptData object
// * that is associated with a specified file descriptor.
// *****************************************************************************
ScriptData * ScriptList::find ( int fd )
{
ScriptData * curr = scripts;
while(curr->sp.readFD != fd && curr!=NULL)
{
curr = curr->next;
}
return curr;
}
// *****************************************************************************
// * ScriptList::insert :
// * This method allows the caller to insert a new ScriptData object
// * into the list of scripts that is managed by this list. Once
// * added to the list the file descriptor associated with the
// * ScriptData object will be placed on the list of file
// * descriptors that will be polled by the cdevSystem object.
// *****************************************************************************
void ScriptList::insert ( ScriptData & script )
{
script.next = scripts;
scripts = &script;
if(fdCount >= fdMax)
{
fdMax = (fdMax>1)?(fdMax*2):16;
fdList = (int *)realloc(fdList, fdMax*sizeof(int));
}
if(fdCount==0) fdList[fdCount++] = selector.readfd();
fdList[fdCount++] = script.sp.readFD;
}
// *****************************************************************************
// * ScriptList::remove :
// * This method calls the remove(fd) method to remove the ScriptData
// * object that is specified by the caller.
// *****************************************************************************
void ScriptList::remove ( ScriptData & script )
{
remove(script.sp.readFD);
}
// *****************************************************************************
// * ScriptList::remove :
// * This method will walk through all scripts in the list until it
// * locates the file descriptor specified by fd. The method will
// * then remove the ScriptData object that is associated with that
// * file descriptor.
// *
// * The fdList and fdCount variables will be updated once the dead
// * file descriptor has been removed.
// *****************************************************************************
void ScriptList::remove ( int fd )
{
ScriptData * prev = NULL;
ScriptData * curr = scripts;
while(curr!=NULL && curr->sp.readFD!=fd)
{
prev = curr;
curr = prev->next;
}
if(curr!=NULL)
{
if(prev!=NULL) prev->next = curr->next;
else scripts = curr->next;
delete curr;
for(fdCount=0, curr = scripts; curr!=NULL; curr=curr->next)
{
fdList[fdCount++] = curr->sp.readFD;
}
}
}
// *****************************************************************************
// * ScriptList::getFd :
// * This method allows the caller to obtain the list of file
// * descriptors that are in use in all scripts. These descriptors
// * will be used to perform ending at the cdevSystem level.
// *
// * Note that this list is updated and maintained each time the
// * user calls "insert" to add a new file descriptor of "remove" to
// * extract an old one.
// *****************************************************************************
int ScriptList::getFd ( int * &fd, int & numFd )
{
fd = fdList;
numFd = fdCount;
return CDEV_SUCCESS;
}
// *****************************************************************************
// * ScriptList::poll :
// * This method is called to poll for events on a list of scripts
// * that are currently executing. This method will return the
// * count of callbacks that were dispatched during this pass through
// * poll.
// *****************************************************************************
int ScriptList::poll ( void )
{
int nHandled = 0;
ScriptData * prev = NULL;
ScriptData * curr = scripts;
// *********************************************************************
// * Clear any events that might be stored in the selector object.
// *********************************************************************
selector.purge();
// *********************************************************************
// * Walk through each script and call the dispatch method to
// * fire callbacks for all file descriptors that have data
// * ready.
// *********************************************************************
for(curr=scripts; curr!=NULL; curr = curr->next)
{
nHandled+=curr->dispatch();
}
// *********************************************************************
// * Walk through the list of scripts again. This time, check
// * the finished flag to determine if each script has run to
// * completion. If so, remove the script from the list of
// * scripts and delete it.
// *********************************************************************
for(prev=NULL, curr=scripts; curr!=NULL; )
{
if(curr->finished)
{
int deadFd = curr->sp.readFD;
curr = curr->next;
remove(deadFd);
}
else {
prev = curr;
curr = prev->next;
}
}
// *********************************************************************
// * Return the total number of callbacks that were fired. This
// * value will be used to allow for polling until at least one
// * event has been processed.
// *********************************************************************
return nHandled;
}
+113
View File
@@ -0,0 +1,113 @@
/*
* -----------------------------------------------------------------------------
* 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 script service.
*
* Author: Walt Akers
*
* -----------------------------------------------------------------------------
*/
#include <sys/ioctl.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <unistd.h>
#include <ctype.h>
#include <cdevData.h>
#include <cdevTranObj.h>
#include <cdevSelector.h>
// *****************************************************************************
// * class ScriptData :
// * This contains the information associated with a single script. A list
// * of ScriptData objects is maintained and accessed through the ScriptList
// * object.
// *
// * Note: because this object is only accessed through the ScriptList
// * object, all data items have been made public to improve performance.
// *****************************************************************************
class ScriptData
{
public:
typedef struct {
int readFD;
int writeFD;
} SocketPair;
ScriptData * next;
SocketPair sp;
cdevTranObj * xobj;
cdevData * data;
char * inputBuf;
int inputBufLen;
int amntRead;
pid_t process;
int finished;
int callbackCount;
ScriptData ( cdevTranObj & Xobj );
~ScriptData (void);
static int data2Buffer (cdevData & data, char *& buf, int &bufLen);
static void dataArray2Buffer (char * output,
char ** ptr,
size_t & ptrIdx,
cdevBounds * bounds,
size_t nBounds,
size_t boundsIdx);
static void dataArray2Buffer (char * output,
double * ptr,
size_t & ptrIdx,
cdevBounds * bounds,
size_t nBounds,
size_t boundsIdx);
static int buffer2Data (char * &buf, cdevData & data );
void fireCallback (int result,
void * arg,
cdevRequestObject &req,
cdevData & data,
int partial=0);
int dispatch (void);
};
// *****************************************************************************
// * class ScriptList:
// * This class maintains a list of ScriptData objects that represent all
// * of the scripts that are currently being run by the ScriptService. The
// * ScriptService object will use the methods of this object to perform
// * operations on the items in the list.
// *
// * Because this class is only accessible through the ScriptService, its
// * internals have been made public to improve performance.
// *****************************************************************************
class ScriptList
{
public:
static cdevSelector selector;
ScriptData * scripts;
int * fdList;
int fdCount;
int fdMax;
ScriptList (void);
~ScriptList (void);
ScriptData * find ( int fd );
void insert ( ScriptData & script );
void remove ( ScriptData & script );
void remove ( int fd );
int getFd ( int * &fd, int & numFd );
int poll ( void );
};
+134
View File
@@ -0,0 +1,134 @@
//-----------------------------------------------------------------------------
// 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 request object.
//
// Author: Walt Akers
//
// Revision History:
// ScriptRequestObject.cc,v
// Revision 1.1 1997/02/11 17:37:24 akers
// Directory restructure
//
// Revision 1.1 1997/01/30 20:35:34 akers
// Initial installation of Script Service
//
//-----------------------------------------------------------------------------
//
#include <ScriptService.h>
#include <ScriptRequestObject.h>
#include <cdevClock.h>
int ScriptRequestObject::syncCode = 0;
// *********************************************************************
// * ScriptRequestObject::ScriptRequestObject :
// * This constructor initializes the internals of a device/message
// * pair associated with the model server.
// *
// * Returns nothing.
// *********************************************************************
ScriptRequestObject::ScriptRequestObject ( char * device, char * message, cdevSystem & system)
: cdevRequestObject(device, message, system), syncFinished(0)
{
}
// *****************************************************************************
// * ScriptRequestObject::sendNoBlock :
// * This function allows the caller to submit an asynchronous message to the
// * server for processing.
// *****************************************************************************
int ScriptRequestObject::sendNoBlock (cdevData * in, cdevData * out)
{
ScriptService * svc = (ScriptService *)service_;
cdevTranObj * xobj = new cdevTranObj(&system_, this, out, &svc->asyncCallback);
cdevData * Data = ((in==NULL)?new cdevData:new cdevData(*in));
return svc->submit(*xobj, *Data);
}
// *****************************************************************************
// * ScriptRequestObject::sendCallback :
// * This function allows the caller to submit an asynchronous message to the
// * server for processing.
// *****************************************************************************
int ScriptRequestObject::sendCallback (cdevData * in, cdevCallback & callback)
{
ScriptService * svc = (ScriptService *)service_;
cdevTranObj * xobj = new cdevTranObj(&system_, this, NULL, new cdevCallback(callback));
cdevData * Data = ((in==NULL)?new cdevData:new cdevData(*in));
xobj->enableDeleteCbk();
return svc->submit(*xobj, *Data);
}
// *****************************************************************************
// * ScriptRequestObject::send :
// * The send interface is used to provide synchronous I/O with the service.
// *
// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error.
// *****************************************************************************
int ScriptRequestObject::send ( cdevData * in, cdevData * out )
{
int status = CDEV_SUCCESS;
ScriptService * svc = (ScriptService *)service_;
cdevCallback * cb = new cdevCallback(ScriptService::syncCallbackFunc, (void *)++syncCode);
cdevTranObj * xobj = new cdevTranObj(&system_, this, out, cb);
cdevData * Data = ((in==NULL)?new cdevData:new cdevData(*in));
xobj->enableDeleteCbk();
if((status = svc->submit(*xobj, *Data))==CDEV_SUCCESS)
{
// *************************************************************
// * I used to wait for a response here only if the outbound
// * cdevData object was non-null. However, that provided
// * unexpected behavior to the client. Now I wait whether
// * output data is expected or not.
// *************************************************************
cdevTimeValue t((double)SEND_WAIT_PERIOD);
cdevClock timer;
timer.schedule(NULL,t);
// *************************************************************
// * WAITING WITH system_.pend():
// * Previously I was using system_.pend() to process events
// * while waiting for the service to respond. This resulted
// * in a lock-up when the connection could not be
// * established or if the connection collapsed while in use.
// *
// * WAITING WITH system_.poll():
// * When in a heavy inbound traffic situation, the calls from other
// * services will trample all over the inbound data coming from the
// * model service. This results in unreliable delivery and
// * processing of messages from the model server.
// *
// * WAITING WITH service_.poll():
// * So far so good.
// *************************************************************
for(syncFinished=0; !syncFinished && !timer.expired(); svc->poll());
if (!syncFinished)
{
status = CDEV_ERROR;
system_.reportError(
CDEV_SEVERITY_ERROR,
"cdevRequestObject",
this,
"Transaction wasn't processed after %i seconds",
SEND_WAIT_PERIOD);
}
else status = syncStatus;
}
return status;
}
+121
View File
@@ -0,0 +1,121 @@
/*
*-----------------------------------------------------------------------------
* 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 request object.
*
* Author: Walt Akers
*
*-----------------------------------------------------------------------------
*/
#if !defined (_SCRIPT_REQUEST_OBJECT_H_)
#define _SCRIPT_REQUEST_OBJECT_H_
#include <cdevRequestObject.h>
#include <cdevTranObj.h>
#include <cdevGroup.h>
#include <cdevErrCode.h>
// *****************************************************************************
// * ScriptRequestObject:
// * The ScriptRequestObject class provides the interface for sending
// * messages to a server. All device/message commands are routed
// * through a ScriptRequestObject either directly or indirectly.
// *****************************************************************************
class ScriptRequestObject : public cdevRequestObject
{
friend class ScriptService;
public:
// *********************************************************************
// * This is how long the system will wait for a reply to be returned
// * from a send.
// *********************************************************************
enum { SEND_WAIT_PERIOD=30 };
// *********************************************************************
// * ScriptRequestObject::ScriptRequestObject :
// * This constructor initializes the internals of a device/message
// * pair associated with the server.
// *
// * Returns nothing.
// *********************************************************************
ScriptRequestObject ( char * device, char * message,
cdevSystem & system = cdevSystem::defaultSystem() );
// *********************************************************************
// * ScriptRequestObject::~ScriptRequestObject :
// * This destructor performs any deallocation or shutdown operations
// * necessary, prior to the destruction of the object.
// *
// * Returns nothing.
// *********************************************************************
virtual ~ScriptRequestObject ( void ) {}
// *********************************************************************
// * ScriptRequestObject::send :
// * The send interface is used to provide synchronous I/O with the
// * service.
// *
// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error.
// *********************************************************************
int send ( cdevData & in, cdevData & out )
{ return send(&in, &out); }
int send ( cdevData * in, cdevData & out )
{ return send(in, &out); }
int send ( cdevData & in, cdevData * out )
{ return send(&in, out); }
int send ( cdevData * in, cdevData * out );
// *********************************************************************
// * ScriptRequestObject::sendNoBlock :
// * The sendNoBlock interface is used in conjunction with cdevGroup
// * or cdevSystem to execute a series of operations. During the
// * early implementation of this product, these functions will be
// * linked directly to the send call.
// *
// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error.
// *********************************************************************
int sendNoBlock (cdevData & in, cdevData & out)
{ return sendNoBlock(&in, &out); }
int sendNoBlock (cdevData * in, cdevData & out)
{ return sendNoBlock(in, &out); }
int sendNoBlock (cdevData & in, cdevData * out)
{ return sendNoBlock(&in, out); }
int sendNoBlock (cdevData * in, cdevData * out);
// *********************************************************************
// * ScriptRequestObject::sendCallback :
// * The sendCallback interface provides asynchronous communications
// * with the server. During the early implementation of this
// * product, these functions will be linked directly to the send
// * call.
// *
// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error.
// *********************************************************************
int sendCallback (cdevData & in, cdevCallback & callback)
{ return sendCallback(&in, callback); }
int sendCallback (cdevData * in, cdevCallback & callback);
// *********************************************************************
// * ScriptRequestObject::className :
// * This function returns the name of the class as a constant string
// *********************************************************************
const char * className ( void ) const { return "ScriptRequestObject"; }
private:
int syncFinished;
int syncStatus;
static int syncCode;
};
#endif /* _SCRIPT_REQUEST_OBJECT_H_ */
+381
View File
@@ -0,0 +1,381 @@
// -----------------------------------------------------------------------------
// 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 script service.
//
// Author: Walt Akers
//
// Revision History:
// ScriptService.cc,v
// Revision 1.3 1997/02/14 20:43:41 akers
// Ongoing improvement
//
// Revision 1.2 1997/02/14 20:06:32 akers
// Ongoing improvement
//
// Revision 1.1 1997/02/11 17:37:27 akers
// Directory restructure
//
// Revision 1.3 1997/01/31 18:51:27 akers
// Ongoing development
//
// Revision 1.2 1997/01/31 16:21:24 akers
// Ongoing development
//
// Revision 1.1 1997/01/30 20:35:35 akers
// Initial installation of Script Service
//
// -----------------------------------------------------------------------------
#include <signal.h>
#include "ScriptService.h"
#include "cdevDirectory.h"
#include "cdevClock.h"
#include "ScriptList.h"
cdevSelector ScriptList::selector;
// ****************************************************************************
// * This function is an interrupt handler that will be executed whenever the
// * program receives a SIGCHLD signal. When called it will execute the poll
// * method of the default server, in order to remove any dead Script Service
// * processes.
// ****************************************************************************
static void SIGCHLD_handler (int)
{
ScriptList::selector.insertEvent();
}
// *********************************************************************
// * newScriptService :
// * This method is called by the cdevSystem object to load the
// * initial instance of the ScriptService.
// *********************************************************************
cdevService * newScriptService ( char * name, cdevSystem * system )
{
signal(SIGCHLD, SIGCHLD_handler);
return new ScriptService(name, *system);
}
// *********************************************************************
// * ScriptService::ScriptService :
// * This is the constructor for the script service. It determines
// * the tag number for the "filename" tag if it does not already
// * exist and allocates the ScriptList object that will be used
// * to hold the individual script instances.
// *********************************************************************
ScriptService::ScriptService ( char * name, cdevSystem & system )
: cdevService(name, system),
FILENAME_TAG(1000),
asyncCallback(asyncCallbackFunc, NULL)
{
scripts = new ScriptList;
while(cdevData::tagC2I("filename", &FILENAME_TAG)!=CDEV_SUCCESS)
{
cdevData::insertTag(++FILENAME_TAG, "filename");
}
}
// *********************************************************************
// * ScriptService::~ScriptService :
// * This is the destructor for the script service,it does nothing
// * but act as a placeholder for the virtual destructor.
// *********************************************************************
ScriptService::~ScriptService ( void )
{
}
// *********************************************************************
// * ScriptService::getRequestObject :
// * This is the interface that cdev objects will use to obtain a
// * ScriptRequestObject object. The ScriptRequestObject
// * represents a combined device and message pair that is associated
// * with the ScriptService.
// *
// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error.
// *********************************************************************
int ScriptService::getRequestObject ( char * device, char * message, cdevRequestObject * &req)
{
req = new ScriptRequestObject (device, message, system_);
return (req ? CDEV_SUCCESS : CDEV_ERROR);
}
// *****************************************************************************
// * ScriptService::getFd
// * This function will return the list of file descriptors that the
// * ScriptService 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 ScriptService::getFd ( int * &fd, int & numFd )
{
fd = scripts->fdList;
numFd = scripts->fdCount;
return CDEV_SUCCESS;
}
// *********************************************************************
// * ScriptService::flush :
// * This function flushes all communications buffers that the
// * service may have open.
// *
// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error.
// *********************************************************************
int ScriptService::flush ( void )
{
return CDEV_SUCCESS;
}
// *****************************************************************************
// * ScriptService::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 ScriptService::poll ( void )
{
if(scripts->fdCount>0) scripts->poll();
return CDEV_SUCCESS;
}
// *****************************************************************************
// * ScriptService::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 ScriptService::pend ( int )
{
while(scripts->fdCount>0 && scripts->poll()==0);
return CDEV_SUCCESS;
}
// *****************************************************************************
// * ScriptService::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 ScriptService::pend ( double seconds, int )
{
if(scripts->fdCount > 0)
{
int nHandled = 0;
cdevTimeValue sec = seconds;
cdevClock timer;
timer.schedule(NULL, sec);
do {
nHandled = scripts->poll();
} while(!nHandled &&
!timer.expired() &&
scripts->fdCount>0);
}
return CDEV_SUCCESS;
}
// *****************************************************************************
// * ScriptService::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 ScriptService::submit ( cdevTranObj &xobj, cdevData &data )
{
int status = CDEV_SUCCESS;
// *********************************************************************
// * Attempt to read the script filename from the DDL file.
// *********************************************************************
ScriptData *script = new ScriptData(xobj);
cdevData temp;
char DDL_request[256];
sprintf (DDL_request,
"resolveServiceData %s %s",
xobj.reqObj_->device().name(),
xobj.reqObj_->message());
if((system_.nameServer()).send(DDL_request, NULL, &temp)==CDEV_SUCCESS)
{
*DDL_request = 0;
temp.get (FILENAME_TAG, DDL_request, 256);
}
else *DDL_request = 0;
// *********************************************************************
// * If the script file was loaded, then begin the process of creating
// * a pipe to retrieve the output of the script, and forking off an
// * additional process to handle execution.
// *********************************************************************
if(*DDL_request)
{
char * parms = NULL;
int bufLen = 0;
// *************************************************************
// * Extract the data from the user provided output cdevData
// * object into a string that can be passed to the script.
// *************************************************************
ScriptData::data2Buffer(data, parms, bufLen);
// *************************************************************
// * Make a copy standard output for later use to restore the
// * standard output file descriptor in the main thread...
// * This is because the behaviour of vfork on some systems
// * will leave the file descriptor in the main thread modified.
// *************************************************************
int fd = dup(1);
// *************************************************************
// * Set the standard output file descriptor to the write file
// * descriptor of the socket pair.
// *************************************************************
dup2(script->sp.writeFD, 1);
// *************************************************************
// * Fork the process to allow the user application to continue
// * running in the original branch, and the script to be
// * executed in the new (child) process.
// *************************************************************
switch((script->process = vfork()))
{
// *****************************************************
// * 0 Indicates that we are in the new child process.
// *****************************************************
case 0:
{
if(bufLen)
{
execl(DDL_request,
DDL_request,
xobj.reqObj_->device().name(),
xobj.reqObj_->message(),
parms, NULL);
}
else {
execl(DDL_request,
DDL_request,
xobj.reqObj_->device().name(),
xobj.reqObj_->message(),
NULL);
}
exit(-1);
}
break;
// *****************************************************
// * -1 Indicates that a new process could not be
// * forked.
// *****************************************************
case -1:
{
// *********************************************
// * Restore the standard output file descriptor
// *********************************************
dup2(fd, 1);
close(fd);
system_.reportError(
CDEV_SEVERITY_ERROR,
"ScriptService",
xobj.reqObj_,
"Failed to fork a new process");
script->fireCallback(CDEV_ERROR,
xobj.userCallback_->userarg(),
*xobj.reqObj_,
*script->data);
status = CDEV_ERROR;
delete script;
}
break;
// *****************************************************
// * Any other value indicates that we are in the parent
// * and the value is the process ID of the new child.
// *****************************************************
default:
{
// *********************************************
// * Restore the standard output file descriptor
// *********************************************
dup2(fd, 1);
close(fd);
// *********************************************
// * Insert the script into the list.
// *********************************************
scripts->insert(*script);
}
break;
}
// *************************************************************
// * Delete parameters (if any).
// *************************************************************
if(bufLen) delete parms;
}
else {
system_.reportError(
CDEV_SEVERITY_ERROR,
"ScriptService",
xobj.reqObj_,
"No filename specified for request %s %s",
xobj.reqObj_->device().name(),
xobj.reqObj_->message());
script->fireCallback(CDEV_ERROR,
xobj.userCallback_->userarg(),
*xobj.reqObj_,
*script->data);
status = CDEV_ERROR;
delete script;
}
return status;
}
// *****************************************************************************
// * ScriptService::getNameServer :
// * This function should obtain the default name server for this object.
// * It does nothing for now.
// *****************************************************************************
int ScriptService::getNameServer(cdevDevice * &ns)
{
ns = 0;
return CDEV_SUCCESS;
}
+166
View File
@@ -0,0 +1,166 @@
/*
*-----------------------------------------------------------------------------
* 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 script service.
*
* Author: Walt Akers
*
*-----------------------------------------------------------------------------
*/
#if !defined (_SCRIPT_SERVICE_H_)
#define _SCRIPT_SERVICE_H_
#include <cdevService.h>
#include "ScriptRequestObject.h"
extern "C" cdevService *newScriptService ( char * name, cdevSystem * system );
class ScriptService : public cdevService
{
friend class ScriptRequestObject;
public:
// *********************************************************************
// * ScriptService::ScriptService :
// * This constructor is responsible for performing all service
// * initialization.
// *********************************************************************
ScriptService ( char * name, cdevSystem & system );
// *********************************************************************
// * ScriptService::~ScriptService :
// * The destructor is protected to prevent it from being called
// * directly. The destructor performs any clean-up or shutdown
// * operations.
// *
// * Returns nothing.
// *********************************************************************
~ScriptService ( void );
// *********************************************************************
// * ScriptService::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
// * ScriptService object.
// *********************************************************************
void installTags ( void );
// *********************************************************************
// * ScriptService::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 ScriptService.
// *
// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error.
// *********************************************************************
int getRequestObject (char *, char *, cdevRequestObject * &);
// *********************************************************************
// * ScriptService::getFd
// * This function will return the list of file descriptors that the
// * ScriptService 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 );
// *********************************************************************
// * ScriptService::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 );
// *********************************************************************
// * ScriptService::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 );
// *********************************************************************
// * ScriptService::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);
// *********************************************************************
// * ScriptService::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);
// *********************************************************************
// * ScriptService::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 submit (cdevTranObj &, cdevData &);
// *********************************************************************
// * ScriptService::getNameServer :
// * This function should obtain the default name server for this
// * object. It does nothing for now.
// *********************************************************************
int getNameServer(cdevDevice * &ns);
// *********************************************************************
// * ScriptService::asyncCallback :
// * This method is called in response to a sendNoBlock reply.
// *********************************************************************
static void asyncCallbackFunc (int, void *, cdevRequestObject &, cdevData &)
{
}
// *********************************************************************
// * ScriptService::syncCallback :
// * This method is called whenever a send is requested from a
// * ScriptRequestObject.
// *********************************************************************
static void syncCallbackFunc ( int status, void *arg, cdevRequestObject &req, cdevData &)
{
ScriptRequestObject * sReq = (ScriptRequestObject *)&req;
int syncCode = (int)arg;
if(syncCode == sReq->syncCode)
{
sReq->syncFinished = 1;
sReq->syncStatus = status;
}
}
protected:
int FILENAME_TAG;
class ScriptList * scripts;
cdevCallback asyncCallback;
};
#endif /* _SCRIPT_SERVICE_H_ */
+39
View File
@@ -0,0 +1,39 @@
ARCH = OS
SHOBJ = YES
include $(CDEV)/extensions/cdevGenericServer/include/makeinclude/Makefile.$(ARCH)
APPNAME = "CDEV/ACE Script Service Tests"
CXXINCLUDES = -I./
BASEBIN = ./
SO_LIBS = $(OSLIBS)
# ******************************************************************************
# * The BINARIES definition names all of the binary files that should be deleted
# * whenever "make clean" is executed.
# ******************************************************************************
BINARIES = $(BASEBIN)/TestProgram $(BASEBIN)/TestProgram2
ifeq ($(SHOBJ), YES)
LIBS = $(CDEVLIBS) $(OSLIBS)
TARGETS = $(BASEBIN)/TestProgram \
$(BASEBIN)/TestProgram2
else
LIBS = $(CDEVLIBS) -lScriptService $(OSLIBS)
TARGETS = $(BASEBIN)/TestProgram \
$(BASEBIN)/TestProgram2
endif
targets : $(TARGETS)
$(BASEBIN)/TestProgram : $(OBJDIR)/TestProgram.o
@rm -f $@
@echo "=> $(CXX) -o $(@F) $(^F)"
@$(LINK.cc) $^ -o $@ $(LIBS)
@echo "<= Done...\n"
$(BASEBIN)/TestProgram2 : $(OBJDIR)/TestProgram2.o
@rm -f $@
@echo "=> $(CXX) -o $(@F) $(^F)"
@$(LINK.cc) $^ -o $@ $(LIBS)
@echo "<= Done...\n"
+27
View File
@@ -0,0 +1,27 @@
service Script
{
tags {filename}
}
class scriptClass
{
verbs {get, set, monitorOn, monitorOff}
attributes
{
attrib0 Script {filename = <>.attrib0};
attrib1 Script {filename = <>.attrib1};
attrib2 Script {filename = <>.attrib2};
attrib3 Script {filename = <>.attrib3};
attrib4 Script {filename = <>.attrib4};
attrib5 Script {filename = <>.attrib5};
attrib6 Script {filename = <>.attrib6};
attrib7 Script {filename = <>.attrib7};
attrib8 Script {filename = <>.attrib8};
attrib9 Script;
}
}
scriptClass :
device0, device1, device2, device3, device4,
device5, device6, device7, device8, device9
;
Binary file not shown.
+76
View File
@@ -0,0 +1,76 @@
#include <cdevSystem.h>
#include <cdevRequestObject.h>
#include <cdevCallback.h>
#include <cdevGroup.h>
void callback (int, void *arg, cdevRequestObject &, cdevData &)
{
static int totalCount = 0;
int * resultCount = (int *)arg;
(*resultCount)++;
fprintf(stdout, "Total count = %i\n", ++totalCount);
}
char * data[2][2][3] =
{
{{"1", "2", "3"}, {"4", "5", "6"}},
{{"1", "2", "3"}, {"4", "5", "6"}},
};
double dData[2][2][3] =
{
{{1.1, 2.2, 3.3}, {4.4, 5.5, 6.6}},
{{1.7, 2.8, 3.9}, {4.11, 5.12, 6.13}}
};
cdevBounds bounds[3] =
{{0, 2},
{0, 2},
{0, 3}};
int main ( void )
{
int resultCount = 0;
cdevData in;
cdevRequestObject & req = cdevRequestObject::attachRef("device0", "get attrib0");
cdevCallback cb (callback, &resultCount);
in.insert("value", (char **)data, 12, 3);
in.setBounds("value", bounds, 3);
in.insert("severity", (double*)dData, 12, 3);
in.setBounds("severity", bounds, 3);
in.insert("status", "Testing");
for(int i=0; i<10; i++)
{
resultCount = 0;
for(int j=0; j<20; j++)
{
req.sendCallback(in, cb);
}
while(resultCount<26) cdevSystem::defaultSystem().poll();
}
}
/*
#include "ScriptList.cc"
int main()
{
cdevData in, out;
char * buf;
int bufLen;
in.insert("value", (char **)data, 12, 3);
in.setBounds("value", bounds, 3);
in.insert("severity", (double*)dData, 12, 3);
in.setBounds("severity", bounds, 3);
in.insert("status", "Testing");
ScriptData::data2Buffer(in, buf, bufLen);
ScriptData::buffer2Data(buf, out);
out.asciiDump();
delete buf;
}
*/
Binary file not shown.
+27
View File
@@ -0,0 +1,27 @@
#include <cdevSystem.h>
#include <cdevRequestObject.h>
#include <cdevCallback.h>
#include <cdevGroup.h>
int done = 0;
void callback (int, void *, cdevRequestObject &, cdevData &data)
{
static int resultCount = 0;
done = cdevCallback::isTransactionDone();
fprintf(stdout, "Result count %i - %s done...\n", ++resultCount, done?" ":"NOT");
if(done) data.asciiDump();
}
int main ( void )
{
cdevData in;
cdevRequestObject & req = cdevRequestObject::attachRef("device0", "get attrib0");
cdevCallback cb (callback, NULL);
req.sendCallback(in, cb);
while(!done)
{
cdevSystem::defaultSystem().pend();
}
}
+386
View File
@@ -0,0 +1,386 @@
#! /bin/csh -f
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n'
printf 'value={{1,2,3},{4,5,6}}\nseverity="NOT so GOOD"\nstatus=0\ncontrolLow={1, 2, 3}\ndone\n'
+1
View File
@@ -0,0 +1 @@
#! /bin/csh
+15
View File
@@ -0,0 +1,15 @@
load /lib/milli.a
load /lib/libc.sl
load /usr/csite4/CenterLine/pa-hpux8/lib/libC.a
load -G /usr/csite/cdev/1.5/lib/hpux-09.XX/libcdev.a
load -D_OS_MAJOR_=9 \
-D_OS_MINOR_=7 \
-I/usr/csite/cdev/1.5/include \
-g -D_HAS_CA -pta \
-I./ -I../src\
../src/ScriptList.cc \
../src/ScriptService.cc \
../src/ScriptRequestObject.cc \
TestProgram2.cc \
-ly -ll -L/lib -lm
link
Binary file not shown.
Binary file not shown.
+43
View File
@@ -0,0 +1,43 @@
ARCH=OS
include ../cdevGenericServer/include/makeinclude/Makefile.$(ARCH)
APPNAME = "CDEV Simple Generic Service"
BASEDIR = $(shell pwd)
INCDIR = $(CDEV)/extensions/cdevGenericServer/include
BINDIR = ./
LIBDIR = $(CDEV)/lib/$(TARGETDIR)
CDEV_INCLUDES = -I$(CDEV)/include
CDEV_LIBS = -lcdev
CDEV_LIBDIR = $(CDEV)/lib/$(TARGETDIR)
CLASS_INCLUDES = -I./ -I$(INCDIR)
CXXEXTRA = -g $(CDEV_INCLUDES) $(CLASS_INCLUDES)
ARLIB_OBJ = .obj/$(TARGETDIR)/cdevSimpleRequestObject.o \
.obj/$(TARGETDIR)/cdevSimpleService.o \
.obj/$(TARGETDIR)/cdevTranNode.o
SHLIB_OBJ = .shobj/$(TARGETDIR)/cdevSimpleRequestObject.o \
.shobj/$(TARGETDIR)/cdevSimpleService.o \
.shobj/$(TARGETDIR)/cdevTranNode.o
TARGETS = $(LIBDIR)/libSimpleService.a $(LIBDIR)/libSimpleService.sl
targets : $(TARGETS)
$(LIBDIR)/libSimpleService.a : $(ARLIB_OBJ)
@rm -f $@
@echo "=> ar ruv $@"
@mkdir -p $(LIBDIR)
@$(LINK.a) $@ $(ARLIB_OBJ)
@ranlib $@ > /dev/null
@echo "\n -------- Completed ----------\n"
$(LIBDIR)/libSimpleService.sl : $(SHLIB_OBJ)
@rm -f $@
@echo "=> $(LINK.so) $(@F)"
@mkdir -p $(LIBDIR)
@$(LINK.so) -o $@ $(SHLIB_OBJ)
@echo "\n -------- Completed ----------\n"
+145
View File
@@ -0,0 +1,145 @@
//-----------------------------------------------------------------------------
// 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 request object.
//
// Author: Walt Akers
//
// Revision History:
// cdevSimpleRequestObject.cc,v
// Revision 1.1 1996/11/21 18:22:19 akers
// Non-Server Oriented Service
//
// Revision 1.1 1996/04/30 15:37:30 akers
// Simple CDEV Service
//
// 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 <cdevTranNode.h>
// *********************************************************************
// * cdevSimpleRequestObject::cdevSimpleRequestObject :
// * This constructor initializes the internals of a device/message
// * pair associated with the model server.
// *
// * Returns nothing.
// *********************************************************************
cdevSimpleRequestObject::cdevSimpleRequestObject ( char * device, char * message, cdevSystem & system)
: cdevRequestObject(device, message, system)
{
cdevData::tagC2I("transaction", &TRANSACT_TAG);
cdevData::tagC2I("transobject", &TRANSOBJ_TAG);
}
// *****************************************************************************
// * cdevSimpleRequestObject::sendNoBlock :
// * This function allows the caller to submit an asynchronous message to the
// * server for processing.
// *****************************************************************************
int cdevSimpleRequestObject::sendNoBlock (cdevData * in, cdevData * out)
{
cdevSimpleService * svc = (cdevSimpleService *)service_;
cdevTranNode * xobj = new cdevTranNode(&system_, this, out, &svc->callback);
char * Device = strdup(deviceName_);
char * Message = strdup(message_);
cdevData * Data = ((in==NULL)?new cdevData:new cdevData(*in));
svc->submit(xobj, Device, Message, Data);
return CDEV_SUCCESS;
}
// *****************************************************************************
// * cdevSimpleRequestObject::sendCallback :
// * This function allows the caller to submit an asynchronous message to the
// * server for processing.
// *****************************************************************************
int cdevSimpleRequestObject::sendCallback (cdevData * in, cdevCallback & callback)
{
cdevSimpleService * svc = (cdevSimpleService *)service_;
cdevTranNode * xobj = new cdevTranNode(&system_, this, NULL, new cdevCallback(callback));
char * Device = strdup(deviceName_);
char * Message = strdup(message_);
cdevData * Data = ((in==NULL)?new cdevData:new cdevData(*in));
xobj->enableDeleteCbk();
svc->submit(xobj, Device, Message, Data);
return CDEV_SUCCESS;
}
// *****************************************************************************
// * cdevSimpleRequestObject::send :
// * The send interface is used to provide synchronous I/O with the service.
// *
// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error.
// *****************************************************************************
int cdevSimpleRequestObject::send ( cdevData * in, cdevData * out )
{
int status = CDEV_SUCCESS;
cdevSimpleService * svc = (cdevSimpleService *)service_;
cdevTranNode * xobj = new cdevTranNode(&system_, this, out, &svc->callback);
char * Device = strdup(deviceName_);
char * Message = strdup(message_);
cdevData * Data = ((in==NULL)?new cdevData:new cdevData(*in));
xobj->permanent(1);
svc->submit(xobj, Device, Message, Data);
// *********************************************************************
// * I used to wait for a response here only if the outbound cdevData
// * object was non-null. However, that provided unexpected behavior
// * to the client. Now I wait whether output data is expected or not.
// *********************************************************************
cdevTimeValue t(30.0);
cdevClock timer;
timer.schedule(NULL,t);
// *********************************************************************
// * WAITING WITH system_.pend():
// * Previously I was using system_.pend() to process events while
// * waiting for the service to respond. This resulted in a lock-up
// * when the connection could not be established or if the
// * connection collapsed while in use.
// *
// * WAITING WITH system_.poll():
// * When in a heavy inbound traffic situation, the calls from other
// * services will trample all over the inbound data coming from the
// * model service. This results in unreliable delivery and
// * processing of messages from the model server.
// *
// * WAITING WITH service_.poll():
// * So far so good.
// *********************************************************************
while(!xobj->finished() && !timer.expired()) service_->poll();
if (!xobj->finished())
{
status = CDEV_ERROR;
system_.reportError(
CDEV_SEVERITY_ERROR,
"cdevRequestObject",
this,
"Transaction wasn't processed after 30 seconds");
}
delete xobj;
return status;
}
+110
View File
@@ -0,0 +1,110 @@
//-----------------------------------------------------------------------------
// 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 request object.
//
// Author: Walt Akers
//
//-----------------------------------------------------------------------------
#if !defined (_CDEV_SIMPLE_REQUEST_OBJECT_H_)
#define _CDEV_SIMPLE_REQUEST_OBJECT_H_
#include <cdevRequestObject.h>
#include <cdevTranObj.h>
#include <cdevGroup.h>
#include <cdevErrCode.h>
// *****************************************************************************
// * cdevSimpleRequestObject:
// * The cdevSimpleRequestObject class provides the interface for sending
// * messages to a server. All device/message commands are routed
// * through a cdevSimpleRequestObject either directly or indirectly.
// *****************************************************************************
class cdevSimpleRequestObject : public cdevRequestObject
{
public:
// *********************************************************************
// * cdevSimpleRequestObject::cdevSimpleRequestObject :
// * This constructor initializes the internals of a device/message
// * pair associated with the server.
// *
// * Returns nothing.
// *********************************************************************
cdevSimpleRequestObject ( char * device, char * message,
cdevSystem & system = cdevSystem::defaultSystem() );
// *********************************************************************
// * cdevSimpleRequestObject::~cdevSimpleRequestObject :
// * This destructor performs any deallocation or shutdown operations
// * necessary, prior to the destruction of the object.
// *
// * Returns nothing.
// *********************************************************************
~cdevSimpleRequestObject ( void ) {}
// *********************************************************************
// * cdevSimpleRequestObject::send :
// * The send interface is used to provide synchronous I/O with the
// * service.
// *
// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error.
// *********************************************************************
int send ( cdevData & in, cdevData & out )
{ return send(&in, &out); }
int send ( cdevData * in, cdevData & out )
{ return send(in, &out); }
int send ( cdevData & in, cdevData * out )
{ return send(&in, out); }
int send ( cdevData * in, cdevData * out );
// *********************************************************************
// * cdevSimpleRequestObject::sendNoBlock :
// * The sendNoBlock interface is used in conjunction with cdevGroup
// * or cdevSystem to execute a series of operations. During the
// * early implementation of this product, these functions will be
// * linked directly to the send call.
// *
// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error.
// *********************************************************************
int sendNoBlock (cdevData & in, cdevData & out)
{ return sendNoBlock(&in, &out); }
int sendNoBlock (cdevData * in, cdevData & out)
{ return sendNoBlock(in, &out); }
int sendNoBlock (cdevData & in, cdevData * out)
{ return sendNoBlock(&in, out); }
int sendNoBlock (cdevData * in, cdevData * out);
// *********************************************************************
// * cdevSimpleRequestObject::sendCallback :
// * The sendCallback interface provides asynchronous communications
// * with the server. During the early implementation of this
// * product, these functions will be linked directly to the send
// * call.
// *
// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error.
// *********************************************************************
int sendCallback (cdevData & in, cdevCallback & callback)
{ return sendCallback(&in, callback); }
int sendCallback (cdevData * in, cdevCallback & callback);
// *********************************************************************
// * cdevSimpleRequestObject::className :
// * This function returns the name of the class as a constant string
// *********************************************************************
const char * className ( void ) const { return "cdevSimpleRequestObject"; }
private:
int TRANSACT_TAG;
int TRANSOBJ_TAG;
};
#endif /* _CDEV_SIMPLE_REQUEST_OBJECT_H_ */
+419
View File
@@ -0,0 +1,419 @@
// -----------------------------------------------------------------------------
// 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;
}
+229
View File
@@ -0,0 +1,229 @@
// -----------------------------------------------------------------------------
// 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_ */
+145
View File
@@ -0,0 +1,145 @@
//-----------------------------------------------------------------------------
// 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 a cdevTranNode. The cdevTranNode is an extension
// of the cdevTranObj. It provides a mechanism for tracking allocated
// and unallocated cdevTranObj objects and prevents inadvertent writes
// to unallocated memory.
//
// Author: Walt Akers
//
// Revision History:
// cdevTranNode.cc,v
// Revision 1.1 1996/11/21 18:22:27 akers
// Non-Server Oriented Service
//
// Revision 1.1 1996/04/30 15:37:41 akers
// Simple CDEV Service
//
// Revision 1.1.1.1 1996/02/28 16:36:20 akers
// Initial release of support for ACE Services
//
// Revision 2.0 1995/10/04 19:21:37 withers
// New CVS repository
//
// Revision 1.1.1.1 1995/10/04 18:45:08 bickley
// CVS start of high-level apps
//
// Revision 1.1.1.1 1995/09/15 17:15:30 withers
// MODEL SERVICE SOURCE
//
//
#include <cdevTranNode.h>
// *****************************************************************************
// * Static class members requiring initialization.
// *****************************************************************************
int cdevTranNode::count = 0;
cdevTranNode * cdevTranNode::freeList = NULL;
cdevTranNode * cdevTranNode::activeList = NULL;
int cdevTranNode::initialized = 1;
// *****************************************************************************
// * cdevTranNode::new :
// * This is the internal mechanism that is used to allocate new cdevTranNode
// * objects. If an object is already available on the freelist, this
// * function will allocate from that list to the activeList. Otherwise, a
// * block of cdevTranNode objects will be allocated to repopulate the
// * freeList first.
// *****************************************************************************
void * cdevTranNode::operator new ( size_t )
{
cdevTranNode * node;
int i;
if(freeList==NULL)
{
freeList = ::new cdevTranNode[16];
for(i=0; i<16; i++)
{
freeList[i].next = (i<15) ? &freeList[i+1] : NULL;
freeList[i].allocated = FALSE;
freeList[i].finished_ = FALSE;
freeList[i].transaction_ = 0;
}
cdevTranNode::count-=16;
}
node = freeList;
freeList = node->next;
node->allocated = TRUE;
node->next = activeList;
activeList = node;
return node;
}
// *****************************************************************************
// * cdevTranNode::delete :
// * This function is used to return an allocated cdevTranNode to the
// * freeList for later allocation to another caller. This function will
// * clear the transaction flag and will clear the allocated flag.
// *****************************************************************************
void cdevTranNode::operator delete ( void * ptr )
{
cdevTranNode * node = activeList;
cdevTranNode * prev = NULL;
if(ptr != NULL)
{
while(node!=NULL && node!=(cdevTranNode *)ptr)
{
prev = node;
node = prev->next;
}
if(node!=NULL)
{
if(prev) prev->next = node->next;
else activeList = node->next;
}
node = (cdevTranNode *)ptr;
node->allocated = FALSE;
node->finished_ = FALSE;
node->transaction_ = 0;
node->next = freeList;
freeList = node;
}
}
// *****************************************************************************
// * cdevTranNode::find:
// * Allows the caller to locate a cdevTranNode using the transaction number.
// *****************************************************************************
cdevTranNode * cdevTranNode::find ( int Transaction )
{
cdevTranNode * node = activeList;
while(node!=NULL && node->transaction_ != Transaction)
{
node = node->next;
}
return node;
}
// *****************************************************************************
// * cdevTranNode::init:
// * Allows the caller to initialize static members of the cdevTranNode class
// *****************************************************************************
void cdevTranNode::init ( void )
{
if(!initialized)
{
count = 0;
freeList = NULL;
activeList = NULL;
initialized = 1;
}
}
+165
View File
@@ -0,0 +1,165 @@
//-----------------------------------------------------------------------------
// 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 a cdevTranNode. The cdevTranNode is an extension
// of the cdevTranObj. It provides a mechanism for tracking allocated
// and unallocated cdevTranObj objects and prevents inadvertent writes
// to unallocated memory.
//
// Author: Walt Akers
//
//
//
#ifndef _CDEV_TRAN_NODE_H_
#define _CDEV_TRAN_NODE_H_
#include <cdevTranObj.h>
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
class cdevTranNode : public cdevTranObj
{
private:
static int count;
static cdevTranNode * freeList;
static cdevTranNode * activeList;
static int initialized;
cdevTranNode * next;
int allocated;
protected:
int finished_;
int permanent_;
int transaction_;
public:
cdevTranNode ( void );
cdevTranNode ( cdevSystem*, cdevRequestObject*, cdevData*, cdevCallback*);
~cdevTranNode( void );
void * operator new ( size_t size );
void operator delete ( void * ptr );
int validate ( int Transaction );
void transaction ( int Transaction );
int transaction ( void );
void finished ( int Finished );
int finished ( void );
void permanent ( int Permanent );
int permanent ( void );
static cdevTranNode * find ( int Transaction );
static void init ( void );
};
// *****************************************************************************
// * cdevTranNode :
// * Allocates a cdevTranNode with no contents.
// *****************************************************************************
inline cdevTranNode::cdevTranNode ( void )
: cdevTranObj(), finished_(FALSE), permanent_(FALSE)
{
if(!initialized) init();
transaction_ = count++;
disableDeleteCbk();
}
// *****************************************************************************
// * cdevTranNode :
// * Allocates a cdevTranNode populated with the required data values.
// *****************************************************************************
inline cdevTranNode::cdevTranNode ( cdevSystem * sys, cdevRequestObject *req,
cdevData * data, cdevCallback * callback )
: cdevTranObj(sys, req, data, callback), finished_(FALSE), permanent_(FALSE)
{
if(!initialized) init();
transaction_ = count++;
disableDeleteCbk();
}
// *****************************************************************************
// * ~cdevTranNode:
// * Deletes the cdevTranNode object.
// *****************************************************************************
inline cdevTranNode::~cdevTranNode ( void )
{
}
// *****************************************************************************
// * cdevTranNode::validate:
// * Allows the user to verify that the cdevTranNode that he has a pointer
// * to, corresponds to the specified Transaction number.
// *****************************************************************************
inline int cdevTranNode::validate ( int Transaction )
{
return (allocated==TRUE && transaction_==Transaction)?CDEV_SUCCESS:CDEV_NOTFOUND;
}
// *****************************************************************************
// * cdevTranNode::transaction:
// * Allows the caller to specify a new transaction number.
// *****************************************************************************
inline void cdevTranNode::transaction ( int Transaction )
{
transaction_ = Transaction;
}
// *****************************************************************************
// * cdevTranNode::transaction:
// * Allows the caller to obtain the transaction number.
// *****************************************************************************
inline int cdevTranNode::transaction ( void )
{
return transaction_;
}
// *****************************************************************************
// * cdevTranNode::finished:
// * Allows the caller to set the finished flag.
// *****************************************************************************
inline void cdevTranNode::finished ( int Finished )
{
finished_ = Finished?TRUE:FALSE;
}
// *****************************************************************************
// * cdevTranNode::finished:
// * Allows the caller to read the contents of the finished flag.
// *****************************************************************************
inline int cdevTranNode::finished ( void )
{
return finished_;
}
// *****************************************************************************
// * cdevTranNode::permanent:
// * Allows the caller to set the permanent flag.
// *****************************************************************************
inline void cdevTranNode::permanent ( int Permanent )
{
permanent_ = Permanent?TRUE:FALSE;
}
// *****************************************************************************
// * cdevTranNode::permanent:
// * Allows the caller to read the contents of the permanent flag.
// *****************************************************************************
inline int cdevTranNode::permanent ( void )
{
return permanent_;
}
#endif /* _CDEV_TRAN_NODE_H_ */
+76
View File
@@ -0,0 +1,76 @@
ARCH = hpux-sl
include $(CDEV)/examples/Makefile.common
SRCROOT = $(CDEV)/extensions/cdevGenericServer
CDEVSHOBJ = /usr/user4/mccops/lib/$(TARGETDIR)
APPNAME = "CDEV Sample Service"
LIBDIR = $(CDEVLIB)
INCDIR = $(SRCROOT)/include
LIBS = -L$(LIBDIR) -lSimpleService \
-L$(CDEVLIB) -lcdev \
-ly -ll -L/lib -lm
LINKLIBS = -L$(LIBDIR) -lSimpleService\
-ly -ll -L/lib -lm
CLASS_INCLUDES = -I./ -I$(INCDIR) -I$(CDEV)/extensions/SimpleService
CXXEXTRA = -pta $(EPICSINCLUDES) $(ACE_INCLUDES) $(CLASS_INCLUDES)
SRCS = SampleService.cc
OBJS = SampleService.o
% : %.cc
@rm -f $@
@echo "=> $(CXX) $< -o $@"
@$(CXX) $(CXXFLAGS) $(CXXEXTRA) $< -o $@ -L$(ACE_LIBDIR) $(ACE_LIBS)
ifeq ($(SHOBJ), YES)
OUTPUTLIB = SampleService.so
targets: buildingService $(CDEVSHOBJ)/$(CDEVVERSION)/SampleService.so
else
OUTPUTLIB = libSampleService.a
targets: buildingService $(CDEV)/lib/$(TARGETDIR)/libSampleService.a
endif
buildingService:
@echo "BUILDING LIBRARY \"$(OUTPUTLIB)\"..."
objClean :
@echo ""
@echo "=> Removing old object files prior to building library"
@rm -rf $(OBJS)
$(CDEVSHOBJ)/$(CDEVVERSION)/SampleService.so : $(OBJS) $(SRCS)
@rm -f $@
@echo "=> Building shared object $@"
@echo " => Pleasuring templates for $@"
@echo "int main() {return 0; }" >dummy.cc
@$(CXX) $(CXXFLAGS) $(CXXEXTRA) dummy.cc $(SRCS) -Wl,+s -ptr./ptSampleService -ptr./ptrepository $(LIBS)
@rm -rf a.out dummy.*
@if test -f ./ptSampleService/*.o; \
then \
echo " => Linking $@ from objects and template objects"; \
$(CXX) -b -o $@ $(OBJS) ptSampleService/*.o $(LINKLIBS); \
else \
echo " => Linking $@ from objects"; \
$(CXX) -b -o $@ $(OBJS) $(LINKLIBS); \
fi
@echo " => $@ finished"
$(CDEV)/lib/$(TARGETDIR)/libSampleService.a : hail buildingService objClean $(OBJS)
@rm -f $@
@echo "=> Building archive library $@"
@echo " => Linking $@ from objects"
@ar ruv libSampleService.a $(OBJS)
@chmod a+r libSampleService.a
@echo " => $@ finished"
clean:
@echo "=> Sample Service"
@echo " => Removing old objects and binaries"
@rm -rf $(OBJS) $(CDEVSHOBJ)/$(TARGETDIR)/SampleService.so a.out *.o *~ core ptrepository ptSampleService
@echo " => Done"
+62
View File
@@ -0,0 +1,62 @@
service ca
{
tags {PV, READONLY}
}
service Sample
{
tags {server}
}
class BPM
{
verbs {get, set, monitorOn, monitorOff}
attributes
{
attrib0 ca {PV = <>.VAL};
attrib1 ca {PV = <>.VAL};
attrib2 ca {PV = <>.VAL};
attrib3 ca {PV = <>.VAL};
attrib4 ca {PV = <>.VAL};
attrib5 ca {PV = <>.VAL};
attrib6 ca {PV = <>.VAL};
attrib7 ca {PV = <>.VAL};
attrib8 ca {PV = <>.VAL};
attrib9 ca {PV = <>.VAL};
}
}
class Samples
{
verbs {get, set, monitorOn, monitorOff}
attributes
{
default Sample;
servers Sample;
attrib0 Sample;
attrib1 Sample;
attrib2 Sample;
attrib3 Sample;
attrib4 Sample;
attrib5 Sample;
attrib6 Sample;
attrib7 Sample;
attrib8 Sample;
attrib9 Sample;
}
messages
{
disconnect Sample;
}
}
BPM :
IPM1S01, IPM1S02, IPM1S03, IPM1S05, IPM1S07,
IPM1S08, IPM1S09
;
Samples :
device0, device1, device2, device3, device4,
device5, device6, device7, device8, device9
;
+32
View File
@@ -0,0 +1,32 @@
#include "SampleService.h"
cdevService * newSampleService ( char * name, cdevSystem * system )
{
return new SampleService(name, *system);
}
SampleService::SampleService ( char * name, cdevSystem & system )
: cdevSimpleService(name, system), var(0)
{
}
SampleService::~SampleService ( void )
{
}
void SampleService::handleOneEvent ( void )
{
cdevTransaction * transaction;
char * device;
char * message;
cdevData * data;
if(dequeue(transaction, device, message, data)==CDEV_SUCCESS)
{
data->insert("device", device);
data->insert("message", message);
data->insert("value", var++);
enqueue(CDEV_SUCCESS, transaction, device, message, data);
}
}
+13
View File
@@ -0,0 +1,13 @@
#include <cdevSimpleService.h>
extern "C" cdevService *newSampleService ( char * name, cdevSystem * system );
class SampleService : public cdevSimpleService
{
int var;
public:
SampleService ( char * name, cdevSystem & system );
virtual ~SampleService ( void );
virtual void handleOneEvent( void );
};
+1
View File
@@ -0,0 +1 @@
=> @@echo = -o libSimpleService.sl;rm -rf /usr/local/i386-glibc22-linux/cdev-1.7.2/lib/Linux/libSimpleService.sl; mkdir -p /usr/local/i386-glibc22-linux/cdev-1.7.2/lib/Linux; g++ -shared libSimpleService.sl
+143
View File
@@ -0,0 +1,143 @@
ifneq ("$(VERBOSE)", "YES")
MAKE := $(MAKE) -s VERBOSE=NO
endif
BASEDIR = $(shell pwd)
BASEINCLUDES = $(BASEDIR)/include
BASEBIN = $(BASEDIR)/bin
BASELIB = $(BASEDIR)/lib
HEADERS = *.h *.i
SRCONLY_DIRS = $(BASEDIR)/cdevClient\
$(BASEDIR)/cdevContextMap\
$(BASEDIR)/cdevMonitorTable\
$(BASEDIR)/cdevPacket\
$(BASEDIR)/cdevServer\
$(BASEDIR)/cdevTagMap\
$(BASEDIR)/common\
LIB_DIRS = $(BASEDIR)/cdevReactor\
$(BASEDIR)/NameServer/src\
$(BASEDIR)/NameServer/cdev\
$(BASEDIR)/lib
UTIL_DIRS = $(BASEDIR)/NameServer/dumpServer
EXAMPLE_DIRS = $(BASEDIR)/NameServer/examples\
$(BASEDIR)/example
TEST_DIRS = $(BASEDIR)/tests\
$(BASEDIR)/cdevReactor/TimerTest\
$(BASEDIR)/cdevReactor/ServerTest
DOC_DIRS = $(BASEDIR)/doc\
HEADER_DIRS = $(BASEDIR)/cdevReactor\
$(BASEDIR)/cdevTagMap\
$(BASEDIR)/cdevContextMap\
$(BASEDIR)/cdevMonitorTable\
$(BASEDIR)/cdevPacket\
$(BASEDIR)/common\
$(BASEDIR)/cdevClient\
$(BASEDIR)/cdevServer\
$(BASEDIR)/NameServer/src\
$(BASEDIR)/NameServer/cdev
CLEAN_DIRS = $(SRCONLY_DIRS)\
$(LIB_DIRS)\
$(UTIL_DIRS)\
$(EXAMPLE_DIRS)\
$(TEST_DIRS)\
$(DOC_DIRS)
PURGE_DIRS = $(SRCONLY_DIRS)\
$(BASEDIR)/cdevReactor\
$(BASEDIR)/NameServer/src\
$(BASEDIR)/NameServer/cdev\
$(BASEDIR)/liteClient\
$(UTIL_DIRS)\
$(EXAMPLE_DIRS)\
$(TEST_DIRS)\
$(DOC_DIRS)
all: directories headers archive shared utils
directories:
@echo "=> Creating directories for binary files"
@mkdir -p $(BASEBIN)
@mkdir -p $(BASELIB)
@echo "<= Done...\n"
headers:
@echo "=> Linking header files to include directory"
@for dir in $(HEADER_DIRS); \
do \
cd $$dir; \
for file in $(HEADERS); \
do \
if test -f $$file; then cp $$dir/$$file $(BASEINCLUDES)/$$file; fi; \
done \
done
@cp $(BASEDIR)/include/makeinclude/Makefile.lib $(BASEDIR)/lib/Makefile
@echo "<= Done...\n"
archive:
@echo "=> Building archive version of libraries"
@for dir in $(LIB_DIRS); \
do \
$(MAKE) -C $$dir SHOBJ=NO; \
done
@echo "<= Done...\n"
shared:
@echo "=> Building shared version of libraries"
@for dir in $(LIB_DIRS); \
do \
$(MAKE) -C $$dir SHOBJ=YES; \
done
@echo "<= Done...\n"
utils:
@echo "=> Building utility programs"
@for dir in $(UTIL_DIRS); \
do \
$(MAKE) -C $$dir SHOBJ=YES; \
done
@echo "<= Done...\n"
examples:
@echo "=> Building example programs"
@for dir in $(EXAMPLE_DIRS); \
do \
$(MAKE) -C $$dir SHOBJ=YES; \
done
@echo "<= Done...\n"
apps:
@echo "=> Building test programs"
@for dir in $(TEST_DIRS); \
do \
$(MAKE) -C $$dir SHOBJ=YES; \
done
@echo "<= Done...\n"
clean:
@echo "=> Cleaning CDEV Generic Server Directories"
@for dir in $(CLEAN_DIRS); \
do \
$(MAKE) -C $$dir clean; \
done
@echo "<= Done...\n"
purge:
@echo "=> Purging CDEV Generic Server Directories"
@echo " => Removing links to header files"
@rm -rf $(BASEINCLUDES)/*.h $(BASEINCLUDES)/*.i
@echo " Done..."
@for dir in $(PURGE_DIRS); \
do \
$(MAKE) -C $$dir purge; \
done
@rm -rf $(BASEDIR)/lib
@rm -rf $(BASEDIR)/bin
@echo "<= Done...\n"
+135
View File
@@ -0,0 +1,135 @@
!IF "$(VERBOSE)" != "YES"
MAKE = $(MAKE) -s VERBOSE=NO
!ENDIF
BASEDIR = $(MAKEDIR)
BASEINCLUDES = $(BASEDIR)\include
BASEBIN = $(BASEDIR)\bin
BASELIB = $(BASEDIR)\lib
HEADERS = dir\*.h dir\*.i
SRCONLY_DIRS = $(BASEDIR)\cdevClient\
$(BASEDIR)\cdevContextMap\
$(BASEDIR)\cdevMonitorTable\
$(BASEDIR)\cdevPacket\
$(BASEDIR)\cdevServer\
$(BASEDIR)\cdevTagMap\
$(BASEDIR)\common\
LIB_DIRS = $(BASEDIR)\cdevReactor\
$(BASEDIR)\NameServer\src\
$(BASEDIR)\NameServer\cdev\
$(BASEDIR)\lib\
$(BASEDIR)\liteClient
UTIL_DIRS = $(BASEDIR)\NameServer\dumpServer
EXAMPLE_DIRS = $(BASEDIR)\NameServer\examples\
$(BASEDIR)\example
TEST_DIRS = $(BASEDIR)\tests\
$(BASEDIR)\cdevReactor\TimerTest\
$(BASEDIR)\cdevReactor\ServerTest
DOC_DIRS = $(BASEDIR)\doc\
HEADER_DIRS = $(BASEDIR)\cdevReactor\
$(BASEDIR)\cdevTagMap\
$(BASEDIR)\cdevContextMap\
$(BASEDIR)\cdevMonitorTable\
$(BASEDIR)\cdevPacket\
$(BASEDIR)\common\
$(BASEDIR)\cdevClient\
$(BASEDIR)\cdevServer\
$(BASEDIR)\NameServer\src\
$(BASEDIR)\NameServer\cdev
CLEAN_DIRS = $(SRCONLY_DIRS)\
$(LIB_DIRS)\
$(UTIL_DIRS)\
$(EXAMPLE_DIRS)\
$(TEST_DIRS)\
$(DOC_DIRS)
all: hail directories headers shared utils fairwell
everything: hail directories headers shared utils examples apps other fairwell
hail:
@echo ---------------------------------------------------------------
@echo Building CDEV Generic Server for Target : $(ARCH)
@echo ---------------------------------------------------------------
fairwell:
@echo ---------------------------------------------------------------
@echo CDEV Generic Server has been built for Target : $(ARCH)
@echo ---------------------------------------------------------------
directories:
@echo =^> Creating directories for binary files
-@if not exist $(BASEBIN) mkdir $(BASEBIN)
-@if not exist $(BASELIB) mkdir $(BASELIB)
-@copy $(BASEINCLUDES)\makeinclude\NMakefile.lib $(BASELIB)\NMakefile.mak
@echo ^<= Done...
headers:
@echo =^> Copying header files to include directory
-@for %d in ($(HEADER_DIRS)) do @for %f in ($(HEADERS:dir=%d)) do @copy %f $(BASEINCLUDES) > nul
@echo ^<= Done...
archives:
@echo =^> Building archive version of libraries
@for %d in ($(LIB_DIRS)) do @cd %d & $(MAKE) /NOLOGO SHOBJ=NO /f NMakefile.mak
@echo <^= Done...
shared:
@echo =^> Building shared version of libraries
@for %d in ($(LIB_DIRS)) do @cd %d & $(MAKE) /NOLOGO SHOBJ=YES /f NMakefile.mak
@echo ^<= Done...
utils:
@echo =^> Building utility programs
@for %d in ($(UTIL_DIRS)) do @cd %d & $(MAKE) /NOLOGO SHOBJ=YES /f NMakefile.mak
@echo ^<= Done...
examples:
@echo =^> Building example programs
@for %d in ($(EXAMPLE_DIRS)) do @cd %d & $(MAKE) /NOLOGO SHOBJ=YES /f NMakefile.mak
@echo ^<= Done...
apps:
@echo =^> Building test programs
@for %d in ($(TEST_DIRS)) do @cd %d & $(MAKE) /NOLOGO SHOBJ=YES /f NMakefile.mak
@echo ^<= Done...
other:
@echo =^> Building miscellaneous applications and libraries
@for %d in ($(SRCONLY_DIRS)) do @cd %d & $(MAKE) /NOLOGO SHOBJ=YES /f NMakefile.mak
@echo ^<= Done...
clean:
@echo =^> Cleaning CDEV Generic Server Directories
@for %d in ($(CLEAN_DIRS)) do @if exist %d\NMakefile.mak cd %d & $(MAKE) /NOLOGO /f NMakefile.mak clean
@echo ^<= Done...
purge:
@echo =^> Purging CDEV Generic Server Directories
@echo ^ ^ ^ =^> Removing header files
-@for %f in ($(BASEINCLUDES)\*.h $(BASEINCLUDES)\*.i) do @erase %f
@echo ^ ^ ^ ^ ^ ^ Done...
@for %d in ($(CLEAN_DIRS)) do @if exist %d\NMakefile.mak cd %d & $(MAKE) /NOLOGO /f NMakefile.mak purge
-@if exist $(BASEDIR)\lib rmdir /s /q $(BASEDIR)\lib
-@if exist $(BASEDIR)\bin rmdir /s /q $(BASEDIR)\bin
@echo ^<= Done...
!IF "$(SUBTARGETDIR)" == ""
subtarget :
-@echo SUBTARGETDIR variable must be defined to build subtargets
!ELSE
!IF "$(SUBTARGET)" == ""
SUBTARGET = all
!ENDIF
subtarget :
@cd $(SUBTARGETDIR)
@$(MAKE) /NOLOGO /f NMakefile.mak $(SUBTARGET)
!ENDIF
+21
View File
@@ -0,0 +1,21 @@
BASEDIR = $(shell pwd)
BUILDDIRS = $(BASEDIR)/src $(BASEDIR)/cdev $(BASEDIR)/dumpServer $(BASEDIR)/examples
CLEANDIRS = $(BASEDIR)/src $(BASEDIR)/cdev $(BASEDIR)/dumpServer $(BASEDIR)/examples
all:
@for dir in $(BUILDDIRS); \
do \
$(MAKE) -C $$dir; \
done
clean:
@for dir in $(CLEANDIRS); \
do \
$(MAKE) -C $$dir clean; \
done
purge:
@for dir in $(CLEANDIRS); \
do \
$(MAKE) -C $$dir purge; \
done
+83
View File
@@ -0,0 +1,83 @@
ARCH = OS
SHOBJ = YES
APPNAME = "Name Server Interface for CDEV"
include ../../include/makeinclude/Makefile.$(ARCH)
TEMPLINKS = rsvcSlist.cc \
rsvcHSlist.cc \
rsvcHash.cc \
rsvcDataStreamer.cc \
rsvcDataEntry.cc \
rsvcData.cc \
rsvcNetData.cc \
rsvcCbk.cc \
rsvcHashable.cc \
rsvcStreamable.cc \
rsvcCallback.cc \
rsvcClient.cc \
rsvcUdpClient.cc
OBJS = $(OBJDIR)/rsvcSlist.o \
$(OBJDIR)/rsvcHSlist.o \
$(OBJDIR)/rsvcHash.o \
$(OBJDIR)/rsvcDataStreamer.o \
$(OBJDIR)/rsvcDataEntry.o \
$(OBJDIR)/rsvcData.o \
$(OBJDIR)/rsvcNetData.o \
$(OBJDIR)/rsvcCbk.o \
$(OBJDIR)/rsvcHashable.o \
$(OBJDIR)/rsvcStreamable.o \
$(OBJDIR)/rsvcCallback.o \
$(OBJDIR)/rsvcClient.o \
$(OBJDIR)/rsvcUdpClient.o \
$(OBJDIR)/rnsService.o \
$(OBJDIR)/rnsRequestObject.o
ifeq ($(SHOBJ),YES)
TARGETS = $(CDEVSHOBJ)/$(CDEVVERSION)/rnsService.so $(BASEBIN)/cdev_test
else
TARGETS = $(BASELIB)/librnsService.a
endif
CXXINCLUDES = -I./
LIBS = -L$(CDEVLIB) -lcdevReactor $(CDEVLIBS) $(OSLIBS)
BINARIES = $(BASEBIN)/cdev_test $(BASELIB)/rnsService.so $(BASELIB)/librnsService.a $(TEMPLINKS)
targets: $(TEMPLINKS) $(TARGETS)
$(TEMPLINKS) :
@cp $^ $@
$(BASEBIN)/cdev_test: $(OBJDIR)/cdev_test.o
$(LINK.cc) $^ $(LIBS) -o $@
$(BASELIB)/librnsService.a: $(OBJS)
$(LINK.a) $@ $^
@$(RANLIB) $@ > /dev/null
@cp $@ $(CDEVLIB)
$(BASELIB)/rnsService.so: $(OBJS)
@mkdir -p $(CDEVSHOBJ)/$(CDEVVERSION)
$(LINK.so) -o $@ $^ $(NETLIBS)
@cp $@ $(CDEVSHOBJ)/$(CDEVVERSION)
$(CDEVSHOBJ)/$(CDEVVERSION)/rnsService.so : $(BASELIB)/rnsService.so
@mkdir -p $(@D)
@echo " => Copying $(@^) to $@"
@rm -f $@
@cp $^ $@
rsvcSlist.cc : ../src/rsvcSlist.cc
rsvcHSlist.cc : ../src/rsvcHSlist.cc
rsvcHash.cc : ../src/rsvcHash.cc
rsvcDataStreamer.cc : ../src/rsvcDataStreamer.cc
rsvcDataEntry.cc : ../src/rsvcDataEntry.cc
rsvcData.cc : ../src/rsvcData.cc
rsvcNetData.cc : ../src/rsvcNetData.cc
rsvcCbk.cc : ../src/rsvcCbk.cc
rsvcHashable.cc : ../src/rsvcHashable.cc
rsvcStreamable.cc : ../src/rsvcStreamable.cc
rsvcCallback.cc : ../src/rsvcCallback.cc
rsvcClient.cc : ../src/rsvcClient.cc
rsvcUdpClient.cc : ../src/rsvcUdpClient.cc
@@ -0,0 +1,118 @@
.SUFFIXES: .cc .obj
APPNAME = Name Server Interface for CDEV
ARCH = WINNT-4.0
BINARIES = $(TEMPLINKS) $(BASEBIN)\cdev_test
include ..\..\include\makeinclude\Makefile.WINNT-4.0
TEMPLINKS = rsvcSlist.cc\
rsvcHSlist.cc\
rsvcHash.cc\
rsvcDataStreamer.cc\
rsvcDataEntry.cc\
rsvcData.cc\
rsvcNetData.cc\
rsvcCbk.cc\
rsvcHashable.cc\
rsvcStreamable.cc\
rsvcCallback.cc\
rsvcClient.cc\
rsvcUdpClient.cc
OBJS = $(OBJDIR)\rsvcSlist.obj\
$(OBJDIR)\rsvcHSlist.obj\
$(OBJDIR)\rsvcHash.obj\
$(OBJDIR)\rsvcDataStreamer.obj\
$(OBJDIR)\rsvcDataEntry.obj\
$(OBJDIR)\rsvcData.obj\
$(OBJDIR)\rsvcNetData.obj\
$(OBJDIR)\rsvcCbk.obj\
$(OBJDIR)\rsvcHashable.obj\
$(OBJDIR)\rsvcStreamable.obj\
$(OBJDIR)\rsvcCallback.obj\
$(OBJDIR)\rsvcClient.obj\
$(OBJDIR)\rsvcUdpClient.obj\
$(OBJDIR)\rnsService.obj\
$(OBJDIR)\rnsRequestObject.obj
!IF "$(SHOBJ)" == "YES"
TARGETS = $(TEMPLINKS) $(CDEVSHOBJ)\$(CDEVVERSION)\rnsService.dll $(BASEBIN)\cdev_test.exe
!ELSE
TARGETS = $(TEMPLINKS) $(CDEVLIB)\rnsService.lib
!ENDIF
CXXINCLUDES = -I.\\
CXXEXTRA_DLL = /D "_RSVC_CORE_EXPORTS_=1"
targets : $(TARGETS)
@erase $(TEMPLINKS)
$(BASEBIN)\cdev_test.exe: $(OBJDIR)\cdev_test.obj
-@if exist $@ erase $@
@echo ^ ^ ^ ^ ^ ^ =^> Linking $(@F)
$(LINK) $(CDEVLIB)\cdev.lib\
$(LINK_EXE_FLAGS) /out:$@ $?
@echo ^ ^ ^ ^ ^ ^ ^ ^ ^ Done...
$(CDEVLIB)\rnsService.lib: $(OBJS)
@echo ^ ^ ^ =^> Linking $(@F)
-@if exist $@ erase $@
-@if not exist $(@D) mkdir $(@D)
@$(LIB32) $(CDEVLIB)\cdev.lib\
$(LINK_LIB_FLAGS) /out:$@ $(OBJS)
@echo ^ ^ ^ ^ ^ ^ Done...
$(CDEVLIB)\rnsService.dll: $(OBJS)
@echo ^ ^ ^ =^> Linking $(@F)
-@if exist $@ erase $@
-@if not exist $(@D) mkdir $(@D)
@$(LIB32) $(CDEVLIB)\cdev.lib\
$(LINK_DLL_FLAGS) /out:$@ /implib:$(@D)\$(@B).lib $(OBJS)
-@if not exist $(CDEVSHOBJ)\$(CDEVVERSION) mkdir $(CDEVSHOBJ)\$(CDEVVERSION)
@copy $@ $(CDEVSHOBJ)\$(CDEVVERSION)\$(@F) > nul
@echo ^ ^ ^ ^ ^ ^ Done...
$(CDEVSHOBJ)\$(CDEVVERSION)\rnsService.dll : $(CDEVLIB)\rnsService.dll
@echo ^ ^ ^ =^> Transfer $(@F) to CDEVSHOBJ directory
-@copy $(CDEVLIB)\rnsService.dll $@
rsvcSlist.cc : ..\src\rsvcSlist.cc
-@$(CREATE_LINK)
rsvcHSlist.cc : ..\src\rsvcHSlist.cc
-@$(CREATE_LINK)
rsvcHash.cc : ..\src\rsvcHash.cc
-@$(CREATE_LINK)
rsvcDataStreamer.cc : ..\src\rsvcDataStreamer.cc
-@$(CREATE_LINK)
rsvcDataEntry.cc : ..\src\rsvcDataEntry.cc
-@$(CREATE_LINK)
rsvcData.cc : ..\src\rsvcData.cc
-@$(CREATE_LINK)
rsvcNetData.cc : ..\src\rsvcNetData.cc
-@$(CREATE_LINK)
rsvcCbk.cc : ..\src\rsvcCbk.cc
-@$(CREATE_LINK)
rsvcHashable.cc : ..\src\rsvcHashable.cc
-@$(CREATE_LINK)
rsvcStreamable.cc : ..\src\rsvcStreamable.cc
-@$(CREATE_LINK)
rsvcCallback.cc : ..\src\rsvcCallback.cc
-@$(CREATE_LINK)
rsvcClient.cc : ..\src\rsvcClient.cc
-@$(CREATE_LINK)
rsvcUdpClient.cc : ..\src\rsvcUdpClient.cc
-@$(CREATE_LINK)
+132
View File
@@ -0,0 +1,132 @@
// simple test for name server cdev interface
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <cdevSystem.h>
#include <cdevRequestObject.h>
#ifdef _WIN32
inline int strcasecmp ( const char * string1, const char * string2 )
{
return _stricmp(string1, string2);
}
#endif
static void entryCallback (int status, void *,
cdevRequestObject&, cdevData& data)
{
if (status == CDEV_SUCCESS || status == CDEV_INCOMPLETE) {
printf ("New server is here \n");
data.asciiDump ();
}
else if (status == CDEV_CBK_FINISHED) {
printf ("entry monitor finished\n");
}
else if (status == CDEV_DISCONNECTED)
printf ("Server is gone\n");
else
printf ("monitor callback failed\n");
}
static void monCallback (int status, void* /* arg */,
cdevRequestObject& /* obj */, cdevData& data)
{
if (status == CDEV_SUCCESS)
data.asciiDump ();
else if (status == CDEV_CBK_FINISHED) {
printf ("monitor finished\n");
data.asciiDump ();
}
else if (status == CDEV_DISCONNECTED)
printf ("server is dead\n");
else
printf ("monitor callback failed\n");
}
int main (int /* argc */, char** /* argv */)
{
cdevSystem& system = cdevSystem::defaultSystem ();
char temp[100];
char comd[100];
printf ("Enter cdev test command\n");
scanf ("%s", comd);
if (strcasecmp (comd, "get") == 0) {
cdevRequestObject* obj = cdevRequestObject::attachPtr ("serverNs", "get");
if (obj) {
cdevData result;
cdevData out;
printf ("enter namd and domain \n");
char name[100], domain[100];
scanf ("%s %s", name, domain);
out.insert ("name", name);
out.insert ("domain", domain);
if (obj->send (out, result) == CDEV_SUCCESS) {
result.asciiDump ();
}
else
printf ("get data failed\n");
}
}
else if (strcasecmp (comd, "monitorOn") == 0) {
cdevRequestObject* obj = cdevRequestObject::attachPtr ("serverNs",
"monitorOn");
if (obj) {
cdevData result;
cdevData out;
printf ("enter namd and domain \n");
char name[100], domain[100];
scanf ("%s %s", name, domain);
out.insert ("name", name);
out.insert ("domain", domain);
cdevCallback cbk (monCallback, 0);
if (obj->sendCallback (out, cbk) != CDEV_SUCCESS)
printf ("monitor data failed\n");
else {
while (1)
system.pend ();
}
// now remove monitor
cdevRequestObject* obj0 = cdevRequestObject::attachPtr ("serverNs",
"monitorOff");
if (obj0) {
if (obj0->sendCallback (out, cbk) != CDEV_SUCCESS)
printf ("monitor off data failed\n");
else
system.pend (20.0);
}
}
}
else if (strcasecmp (comd, "monitorEntry") == 0) {
cdevRequestObject* obj = cdevRequestObject::attachPtr ("serverNs",
"monitorEntry");
if (obj) {
cdevCallback cbk (entryCallback, 0);
if (obj->sendCallback (0, cbk) != CDEV_SUCCESS)
printf ("monitor entry failed\n");
else {
while (1)
system.pend ();
}
// now remove monitor
cdevRequestObject* obj0 = cdevRequestObject::attachPtr ("serverNs",
"monitorEntryOff");
if (obj0) {
if (obj0->sendCallback (0, cbk) != CDEV_SUCCESS)
printf ("monitor off data failed\n");
else
system.pend (20.0);
}
}
}
return 0;
}
+17
View File
@@ -0,0 +1,17 @@
service rns {
tags {PV}
}
class RNS {
messages {
get rns;
monitorOn rns;
monitorOff rns;
monitorEntry rns;
monitorEntryOff rns;
}
}
RNS :
serverNs
;
@@ -0,0 +1,54 @@
//-----------------------------------------------------------------------------
// Copyright (c) 1994,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:
// Name Server Monitor Object
//
// Author: Jie Chen
//
//
//
#ifndef _RNS_MONITOR_OBJ_H
#define _RNS_MONITOR_OBJ_H
#include <cdevMonitorObj.h>
class rnsRequestObject;
class rnsMonitorObj : public cdevMonitorObj
{
public:
// constructor and destructor
rnsMonitorObj (cdevTranObj& tranObj)
:cdevMonitorObj (tranObj), out_ (0), started_ (1)
{
#ifdef _TRACE_OBJECTS
printf (" Create rnsMonitorObj Class Object\n");
#endif
}
~rnsMonitorObj (void)
{
#ifdef _TRACE_OBJECTS
printf (" Delete rnsMonitorObj Class Object\n");
#endif
if (out_)
delete out_;
}
const char* className (void) const {return "rnsMonitorObj";}
// out bound cdevdata
cdevData* out_;
// whether this monitor callback is restarted or not
int started_;
};
#endif
@@ -0,0 +1,439 @@
#include <cdevSystem.h>
#include <cdevRequestObject.h>
#include <cdevData.h>
#include <cdevCallback.h>
class rnsQueryCollector
{
private:
cdevData * data;
int deleteFlag;
unsigned char * byteData;
short * shortData;
unsigned short * ushortData;
long * longData;
unsigned long * ulongData;
float * floatData;
double * doubleData;
cdev_TS_STAMP * tsData;
size_t byteCnt;
size_t shortCnt;
size_t ushortCnt;
size_t longCnt;
size_t ulongCnt;
size_t floatCnt;
size_t doubleCnt;
size_t tsCnt;
public:
rnsQueryCollector ( cdevData & userData, int deleteData = 0 )
: data(&userData), deleteFlag(deleteData),
byteData(NULL), shortData(NULL), ushortData(NULL),
longData(NULL), ulongData(NULL), floatData(NULL),
doubleData(NULL), tsData(NULL), byteCnt(0),
shortCnt(0), ushortCnt(0), longCnt(0), ulongCnt(0),
floatCnt(0), doubleCnt(0), tsCnt(0)
{
data->remove();
}
~rnsQueryCollector ( void )
{
if(deleteFlag) delete data;
if(byteData) delete byteData;
if(shortData) delete shortData;
if(ushortData) delete ushortData;
if(longData) delete longData;
if(ulongData) delete ulongData;
if(floatData) delete floatData;
if(doubleData) delete doubleData;
if(tsData) delete tsData;
}
cdevData * getData ( void ) { return data; }
void clearData ( void ) { data->remove(); }
inline int collect ( cdevData & userData );
private:
inline int collectAttribute ( cdevData & userData, int tag, int position );
inline void collectByteAttribute ( cdevData & userData, int tag, int position );
inline void collectShortAttribute ( cdevData & userData, int tag, int position );
inline void collectUShortAttribute ( cdevData & userData, int tag, int position );
inline void collectLongAttribute ( cdevData & userData, int tag, int position );
inline void collectULongAttribute ( cdevData & userData, int tag, int position );
inline void collectFloatAttribute ( cdevData & userData, int tag, int position );
inline void collectDoubleAttribute ( cdevData & userData, int tag, int position );
inline void collectStringAttribute ( cdevData & userData, int tag, int position );
inline void collectTimestampAttribute ( cdevData & userData, int tag, int position );
};
// *****************************************************************************
// * class rnsQueryCallback :
// * This class provides the methods to allow a rnsQueryCollector to be
// * incorporated into a cdevCallback. The localCallback function will
// * be called with results until the data has been completely collected,
// * and only then will the user callback be executed - providing full
// * data.
// *****************************************************************************
class rnsQueryCallback : public cdevCallback
{
private:
rnsQueryCollector collector;
cdevCallback callback;
public:
rnsQueryCallback ( cdevCallback & Callback )
: cdevCallback(), callback(Callback), collector(*(new cdevData), 1)
{
userarg_ = this;
function_ = rnsQueryCallback::localCallback;
}
virtual ~rnsQueryCallback ( void )
{
}
static void localCallback ( int status, void * arg, cdevRequestObject & req, cdevData & data)
{
rnsQueryCallback * qCallback;
if((qCallback = (rnsQueryCallback *)arg)!=NULL)
{
if(status==CDEV_SUCCESS ||
status==CDEV_INCOMPLETE)
{
qCallback->collector.collect(data);
}
if(status==CDEV_SUCCESS ||
status==CDEV_ERROR ||
status==CDEV_NOTFOUND ||
status==CDEV_MSG_ERR)
{
qCallback->callback.fireCallback(status, qCallback->callback.userarg(),
req, *qCallback->collector.getData(), 0);
}
}
}
};
// *****************************************************************************
// * rnsQueryCollector::collect :
// * This method is called when a cdevData object needs to be appended to
// * the cdevData object that is serving as a collection. This method will
// * transfer each of the data items in the userData object to the proper
// * position in the local data object.
// *****************************************************************************
int rnsQueryCollector::collect ( cdevData & userData )
{
int cnt = 0;
size_t size = 0;
cdevDataIterator iter(&userData);
cdevDataIterator dIter(data);
// *********************************************************************
// * Look through the existing data and determine the largest number
// * of items that exist in a single tagged item. This value will be
// * used to specify the position of the data that is being added to the
// * array.
// *********************************************************************
dIter.init();
while(dIter.tag()!=0)
{
size_t elems = 0;
data->getElems(dIter.tag(), &elems);
if(elems>size) size = elems;
++dIter;
}
// *********************************************************************
// * Walk through the list of tagged data items that are stored in the
// * inbound data object. Call the collectAttribute method for each
// * data item. This method will copy the contents of the inbound
// * data object to the correct position in the local data object.
// *********************************************************************
iter.init();
while(iter.tag()!=0)
{
cnt+=(collectAttribute(userData, iter.tag(), size)==0)?1:0;
++iter;
}
// *********************************************************************
// * Return the count of data items that were assimilated into the
// * local data object.
// *********************************************************************
return cnt;
}
// *****************************************************************************
// * rnsQueryCollector::collectAttribute :
// * This method will assimilate a single attribute from the specified
// * userData object into the local cdevData object at the specified
// * position.
// *****************************************************************************
int rnsQueryCollector::collectAttribute ( cdevData & userData, int tag, int position )
{
cdevSystem & sys = cdevSystem::defaultSystem();
int result = 0;
size_t dim = 0;
size_t userDim = 0;
cdevDataTypes type = data->getType(tag);
cdevDataTypes userType = userData.getType(tag);
if(userData.getDim(tag, &dim)==CDEV_NOTFOUND || dim > 0)
{
sys.reportError(CDEV_SEVERITY_ERROR, "Name Server", NULL,
"Cannot add array data to query reply");
result = -1;
}
else if(data->getDim(tag, &dim)!=CDEV_NOTFOUND && dim > 1)
{
sys.reportError(CDEV_SEVERITY_ERROR, "Name Server", NULL,
"Cannot assemble a query with multi-dimensional data");
result = -1;
}
else if (userType == CDEV_INVALID)
{
sys.reportError(CDEV_SEVERITY_ERROR, "Name Server", NULL,
"Inbound query data object has invalid data type");
result = -1;
}
else {
if(type!=CDEV_INVALID)
{
if(type<CDEV_TIMESTAMP && userType<CDEV_TIMESTAMP)
{
type = (type>userType)?type:userType;
}
else if(type==CDEV_TIMESTAMP) type = userType;
}
else type = userType;
switch(type)
{
case CDEV_BYTE:
collectByteAttribute(userData, tag, position);
break;
case CDEV_INT16:
collectShortAttribute(userData, tag, position);
break;
case CDEV_UINT16:
collectUShortAttribute(userData, tag, position);
break;
case CDEV_INT32:
collectLongAttribute(userData, tag, position);
break;
case CDEV_UINT32:
collectULongAttribute(userData, tag, position);
break;
case CDEV_FLOAT:
collectFloatAttribute(userData, tag, position);
break;
case CDEV_DOUBLE:
collectDoubleAttribute(userData, tag, position);
break;
case CDEV_STRING:
collectStringAttribute(userData, tag, position);
break;
case CDEV_TIMESTAMP:
collectTimestampAttribute(userData, tag, position);
break;
default:
result = -1;
break;
}
}
return result;
}
// *****************************************************************************
// * rnsQueryCollector::collectByteAttribute :
// * This method will transfer the byte attribute stored in the userData
// * object into the local cdevData object at the specified position.
// *****************************************************************************
void rnsQueryCollector::collectByteAttribute (cdevData & userData, int tag, int position )
{
if((position+1)>byteCnt)
{
if(byteData!=NULL) delete byteData;
byteCnt = ((position+1)>100)?(position+100):100;
byteData = new unsigned char [byteCnt];
}
memset(byteData, 0, byteCnt*sizeof(unsigned char));
data->get(tag, byteData);
userData.get(tag, &byteData[position]);
data->insert(tag, byteData, position+1);
}
// *****************************************************************************
// * rnsQueryCollector::collectShortAttribute :
// * This method will transfer the short attribute stored in the userData
// * object into the local cdevData object at the specified position.
// *****************************************************************************
void rnsQueryCollector::collectShortAttribute (cdevData & userData, int tag, int position )
{
if((position+1)>shortCnt)
{
if(shortData!=NULL) delete shortData;
shortCnt = ((position+1)>100)?(position+100):100;
shortData = new short [shortCnt];
}
memset(shortData, 0, shortCnt*sizeof(short));
data->get(tag, shortData);
userData.get(tag, &shortData[position]);
data->insert(tag, shortData, position+1);
}
// *****************************************************************************
// * rnsQueryCollector::collectUShortAttribute :
// * This method will transfer the unsigned short attribute stored in the
// * userData object into the local cdevData object at the specified
// * position.
// *****************************************************************************
void rnsQueryCollector::collectUShortAttribute (cdevData & userData, int tag, int position )
{
if((position+1)>ushortCnt)
{
if(ushortData!=NULL) delete ushortData;
ushortCnt = ((position+1)>100)?(position+100):100;
ushortData = new unsigned short [ushortCnt];
}
memset(ushortData, 0, ushortCnt*sizeof(unsigned short));
data->get(tag, ushortData);
userData.get(tag, &ushortData[position]);
data->insert(tag, ushortData, position+1);
}
// *****************************************************************************
// * rnsQueryCollector::collectLongAttribute :
// * This method will transfer the long attribute stored in the
// * userData object into the local cdevData object at the specified
// * position.
// *****************************************************************************
void rnsQueryCollector::collectLongAttribute (cdevData & userData, int tag, int position )
{
if((position+1)>longCnt)
{
if(longData!=NULL) delete longData;
longCnt = ((position+1)>100)?(position+100):100;
longData = new long [longCnt];
}
memset(longData, 0, longCnt*sizeof(long));
data->get(tag, longData);
userData.get(tag, &longData[position]);
data->insert(tag, longData, position+1);
}
// *****************************************************************************
// * rnsQueryCollector::collectULongAttribute :
// * This method will transfer the unsigned long attribute stored in the
// * userData object into the local cdevData object at the specified
// * position.
// *****************************************************************************
void rnsQueryCollector::collectULongAttribute (cdevData & userData, int tag, int position )
{
if((position+1)>ulongCnt)
{
if(ulongData!=NULL) delete ulongData;
ulongCnt = ((position+1)>100)?(position+100):100;
ulongData = new unsigned long [ulongCnt];
}
memset(ulongData, 0, ulongCnt*sizeof(unsigned long));
data->get(tag, ulongData);
userData.get(tag, &ulongData[position]);
data->insert(tag, ulongData, position+1);
}
// *****************************************************************************
// * rnsQueryCollector::collectFloatAttribute :
// * This method will transfer the float attribute stored in the
// * userData object into the local cdevData object at the specified
// * position.
// *****************************************************************************
void rnsQueryCollector::collectFloatAttribute (cdevData & userData, int tag, int position )
{
if((position+1)>floatCnt)
{
if(floatData!=NULL) delete floatData;
floatCnt = ((position+1)>100)?(position+100):100;
floatData = new float [floatCnt];
}
memset(floatData, 0, floatCnt*sizeof(float));
data->get(tag, floatData);
userData.get(tag, &floatData[position]);
data->insert(tag, floatData, position+1);
}
// *****************************************************************************
// * rnsQueryCollector::collectDoubleAttribute :
// * This method will transfer the double attribute stored in the
// * userData object into the local cdevData object at the specified
// * position.
// *****************************************************************************
void rnsQueryCollector::collectDoubleAttribute (cdevData & userData, int tag, int position )
{
if((position+1)>doubleCnt)
{
if(doubleData!=NULL) delete doubleData;
doubleCnt = ((position+1)>100)?(position+100):100;
doubleData = new double [doubleCnt];
}
memset(doubleData, 0, doubleCnt*sizeof(double));
data->get(tag, doubleData);
userData.get(tag, &doubleData[position]);
data->insert(tag, doubleData, position+1);
}
// *****************************************************************************
// * rnsQueryCollector::collectStringAttribute :
// * This method will transfer the string attribute stored in the
// * userData object into the local cdevData object at the specified
// * position.
// *****************************************************************************
void rnsQueryCollector::collectStringAttribute (cdevData & userData, int tag, int position )
{
int i;
char blank = 0;
char ** stringData = new char * [ position+1 ];
memset(stringData, 0, (position+1)*sizeof(char *));
data->get(tag, stringData);
userData.get(tag, &stringData[position]);
for(i=0; i<position+1; i++)
{
if(stringData[i] == NULL) stringData[i] = &blank;
}
data->insert(tag, stringData, position+1);
for(i=0; i<position+1; i++)
{
if(stringData[i]!=&blank) delete stringData[i];
}
delete stringData;
}
// *****************************************************************************
// * rnsQueryCollector::collectTimestampAttribute :
// * This method will transfer the time stamp attribute stored in the
// * userData object into the local cdevData object at the specified
// * position.
// *****************************************************************************
void rnsQueryCollector::collectTimestampAttribute (cdevData & userData, int tag, int position )
{
if((position+1)>tsCnt)
{
if(tsData!=NULL) delete tsData;
tsCnt = ((position+1)>100)?(position+100):100;
tsData = new cdev_TS_STAMP [tsCnt];
}
memset(tsData, 0, tsCnt);
data->get(tag, tsData);
userData.get(tag, &tsData[position]);
data->insert(tag, tsData, position+1);
}
@@ -0,0 +1,752 @@
//-----------------------------------------------------------------------------
// Copyright (c) 1994,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:
// Implementation of rnsRequesObject Class
//
// Author: Jie Chen
//
// Revision History:
// rnsRequestObject.cc,v
// Revision 1.7 1998/04/01 15:32:12 chen
// fix transaction done flag
//
// Revision 1.6 1998/03/19 18:31:43 chen
// add monitorEntry capability
//
// Revision 1.5 1998/02/09 13:35:47 chen
// duplicate cdev data in the monitor object
//
// Revision 1.4 1998/02/06 15:11:25 chen
// add connection management for name server
//
// Revision 1.3 1998/02/05 15:59:19 akers
// Ongoing development
//
// Revision 1.2 1998/01/30 18:31:37 akers
// Ongoing development
//
// Revision 1.1 1998/01/22 17:07:51 akers
// Addition of new NameServer
//
//
//
#include <cdevErrCode.h>
#include <cdevCommon.h>
#include <rnsMonitorObj.h>
#include <cdevClock.h>
#include "rnsService.h"
#include "rnsRequestObject.h"
#include "rnsQueryCollector.h"
#include <rsvcClient.h>
char* rnsRequestObject::stags_[] = {"name", "domain"};
int rnsRequestObject::numstags_ = 2;
#ifdef _WIN32
inline int strcasecmp ( const char * string1, const char * string2 )
{
return stricmp(string1, string2);
}
#endif
// *****************************************************************************
// * The localQuerySynchronizer class has been added to allow me to make
// * synchronous requests to query the NameServer.
// *****************************************************************************
class localQuerySynchronizer
{
public:
static int cbDone;
static long cbIdent;
static cdevData cbData;
static cdevCallback getCallbackObj ( void )
{
cbData.remove();
cbDone = 0;
cbIdent++;
cdevCallback cbObj(callback, (void *)cbIdent);
return cbObj;
}
static void callback ( int /*status*/, void * userarg, cdevRequestObject &/*reqObj*/, cdevData &data)
{
if(((long)userarg)==cbIdent)
{
cbDone = 1;
cbData = data;
}
}
};
int localQuerySynchronizer::cbDone = 0;
long localQuerySynchronizer::cbIdent = 0;
cdevData localQuerySynchronizer::cbData;
rnsRequestObject::rnsRequestObject (char* device, char* msg,
rnsService* svc,
cdevSystem& system)
:cdevRequestObject (device, msg, system), client_ (0)
{
#ifdef _TRACE_OBJECTS
printf (" Create rnsRequestObject Class Object\n");
#endif
client_ = &(svc->client_);
// convert msg to integer action
rnsRequestObject::findAction (msg, action_);
}
rnsRequestObject::~rnsRequestObject (void)
{
#ifdef _TRACE_OBJECTS
printf (" Delete rnsRequestObject Class Object\n");
#endif
}
int
rnsRequestObject::getState (void)
{
if (client_->connected ())
return CDEV_STATE_CONNECTED;
return CDEV_STATE_NOTCONNECTED;
}
int
rnsRequestObject::sendCallback (cdevData& out, cdevCallback& cbk)
{
return sendCallback (&out, cbk);
}
int
rnsRequestObject::sendCallback (cdevData* out, cdevCallback& userCallback)
{
if (deferExecution (out, &userCallback))
return CDEV_SUCCESS;
int status = CDEV_SUCCESS;
cdevTranObj* xobj = 0;
rnsMonitorObj* mobj = 0;
rnsService* nservice = (rnsService *)service_;
// copy userCallback into the following callback, which will free
// the user from worrying about cdevCallback object
// note: cdevCallback's new operator is an overloaded operator
cdevCallback* callback = 0;
if (client_->connected ()) {
switch (action_) {
case rnsRequestObject::GET:
{
if (out == 0)
return CDEV_INVALIDARG;
callback = new cdevCallback (userCallback);
xobj = new cdevTranObj (&system_, this, 0, callback);
rsvcData outdata;
if (rnsRequestObject::dataCdevToRsvc (*out, outdata) != CDEV_SUCCESS)
status = CDEV_INVALIDARG;
else {
if (client_->getValue (_RSVC_CDEV_SERVERS, outdata,
&(rnsRequestObject::getCallback),
(void *)xobj) != CDEV_SUCCESS)
status = CDEV_IOFAILED;
}
if (status != CDEV_SUCCESS)
delete xobj;
}
break;
case rnsRequestObject::QUERY:
{
if (out == 0)
return CDEV_INVALIDARG;
callback = (cdevCallback *)new rnsQueryCallback(userCallback);
xobj = new cdevTranObj (&system_, this, 0, callback);
mobj = new rnsMonitorObj (*xobj);
char qmsg[1024];
if (out->get ("queryMsg", qmsg, sizeof (qmsg)) != CDEV_SUCCESS)
status = CDEV_INVALIDARG;
else {
mobj->out_ = new cdevData (*out);
if (client_->query (_RSVC_CDEV_SERVERS, qmsg,
&(rnsRequestObject::queryCallback),
(void *)mobj) != CDEV_SUCCESS)
status = CDEV_IOFAILED;
else
nservice->addMonitorObject (mobj);
}
if (status != CDEV_SUCCESS) {
delete xobj;
delete mobj;
}
}
break;
case rnsRequestObject::MONITORON:
{
if (out == 0)
return CDEV_INVALIDARG;
if (nservice->hasCallback (userCallback))
return CDEV_INVALIDARG;
callback = new cdevCallback (userCallback);
xobj = new cdevTranObj (&system_, this, 0, callback);
mobj = new rnsMonitorObj (*xobj);
rsvcData outdata;
if (rnsRequestObject::dataCdevToRsvc (*out, outdata) != CDEV_SUCCESS)
status = CDEV_INVALIDARG;
else {
mobj->out_ = new cdevData (*out);
if (client_->monitorValue (_RSVC_CDEV_SERVERS, outdata,
&(rnsRequestObject::monitorCallback),
(void *)mobj) != CDEV_SUCCESS)
status = CDEV_IOFAILED;
else
nservice->addMonitorObject (mobj);
}
if (status != CDEV_SUCCESS) {
delete xobj;
delete mobj;
}
}
break;
case rnsRequestObject::MONITOROFF:
{
if (out == 0)
return CDEV_INVALIDARG;
rnsMonitorObj* mobj = 0;
rsvcData outdata;
if (rnsRequestObject::dataCdevToRsvc (*out, outdata) != CDEV_SUCCESS)
status = CDEV_INVALIDARG;
else {
if ((mobj = nservice->hasCallback (userCallback)) == 0) {
printf ("this callback function is not registered\n");
status = CDEV_INVALIDARG;
}
else
status = monitorOff (outdata, mobj);
}
}
break;
case rnsRequestObject::MONITORENTRY:
{
if (nservice->hasCallback (userCallback))
return CDEV_INVALIDARG;
callback = new cdevCallback (userCallback);
xobj = new cdevTranObj (&system_, this, 0, callback);
mobj = new rnsMonitorObj (*xobj);
rsvcData empty;
if (client_->monitorIncomingEntries (_RSVC_CDEV_SERVERS, empty,
&(rnsRequestObject::entryCallback),
(void *)mobj) != CDEV_SUCCESS)
status = CDEV_IOFAILED;
else
nservice->addMonitorObject (mobj);
if (status != CDEV_SUCCESS) {
delete xobj;
delete mobj;
}
}
break;
case rnsRequestObject::MONITORENTRYOFF:
{
rnsMonitorObj* mobj = 0;
if ((mobj = nservice->hasCallback (userCallback)) == 0) {
#ifdef _CDEV_DEBUG
printf ("this callback function is not registered\n");
#endif
status = CDEV_INVALIDARG;
}
else
status = monitorEntryOff (mobj);
}
break;
default:
status = CDEV_INVALIDARG;
break;
}
}
else
status = CDEV_NOTCONNECTED;
return status;
}
int
rnsRequestObject::sendMonitor (rnsMonitorObj* mobj)
{
rsvcData outdata;
int status = CDEV_SUCCESS;
if (rnsRequestObject::dataCdevToRsvc (*mobj->out_, outdata)!= CDEV_SUCCESS) {
mobj->started_ = 1;
status = CDEV_INVALIDARG;
}
else {
if ((status = client_->monitorValue (_RSVC_CDEV_SERVERS, outdata,
&(rnsRequestObject::monitorCallback),
(void *)mobj)) != CDEV_SUCCESS)
mobj->started_ = 1;
}
return status;
}
int
rnsRequestObject::sendEntryMonitor (rnsMonitorObj* mobj)
{
int status = CDEV_SUCCESS;
rsvcData empty;
if ((status = client_->monitorIncomingEntries (_RSVC_CDEV_SERVERS, empty,
&(rnsRequestObject::entryCallback),
(void *)mobj)) != CDEV_SUCCESS)
mobj->started_ = 1;
return status;
}
void
rnsRequestObject::getCallback (int status, void* arg, rsvcData* data)
{
cdevTranObj* xobj = (cdevTranObj *)arg;
// if a callback has been discarded, do not do anything
if (xobj->isTrash ()) {
delete xobj;
return;
}
cdevCallback* cbk = xobj->userCallback_;
cdevRequestObject* obj = xobj->reqObj_;
cdevData* rda = xobj->resultData_;
cdevData result;
if (rda) // send no block
rda->remove ();
else
rda = &result;
if (status == RSVC_SUCCESS)
rnsRequestObject::dataRsvcToCdev (*data, *rda);
if (cbk)
cbk->fireCallback (status, cbk->userarg (), *obj, result, 0);
delete xobj;
}
void
rnsRequestObject::queryCallback (int status, void* arg, rsvcData* data)
{
rnsMonitorObj* mobj = (rnsMonitorObj *)arg;
cdevCallback* cbk = mobj->userCallback_;
cdevRequestObject* obj = mobj->reqObj_;
cdevData result;
int cbk_finished = 1;
// first time this callback is called
if (mobj->tobj_) {
delete mobj->tobj_;
mobj->tobj_ = 0;
}
if (status == RSVC_ERROR || status == RSVC_NOTFOUND)
cbk->fireCallback (status, cbk->userarg (), *obj, result, 0);
else if (status == RSVC_INCOMPLETE) {
rnsRequestObject::dataRsvcToCdev (*data, result);
cbk->fireCallback (status, cbk->userarg (), *obj, result, 1);
cbk_finished = 0;
}
else if (status == RSVC_QUERYMSG_ERR)
cbk->fireCallback (CDEV_MSG_ERR, cbk->userarg (), *obj, result, 0);
else {
rnsRequestObject::dataRsvcToCdev (*data, result);
cbk->fireCallback (status, cbk->userarg (), *obj, result, 0);
}
if (cbk_finished) {
rnsRequestObject* nsreq = (rnsRequestObject *)obj;
nsreq->removeMonitorObject (mobj);
}
}
void
rnsRequestObject::monitorCallback (int status, void* arg, rsvcData* data)
{
rnsMonitorObj* mobj = (rnsMonitorObj *)arg;
cdevCallback* cbk = mobj->userCallback_;
cdevRequestObject* obj = mobj->reqObj_;
cdevData result;
int cbk_finished = 1;
// first time this callback is called
if (mobj->tobj_) {
delete mobj->tobj_;
mobj->tobj_ = 0;
}
if (status == RSVC_SUCCESS) {
rnsRequestObject::dataRsvcToCdev (*data, result);
cbk->fireCallback (status, cbk->userarg (), *obj, result, 1);
cbk_finished = 0;
if (!mobj->started_)
mobj->started_ = 1;
}
else if (status == RSVC_CBK_FINISHED) {
rnsRequestObject::dataRsvcToCdev (*data, result);
if (mobj->started_)
cbk->fireCallback (status, cbk->userarg (), *obj, result, 0);
}
else {
if (mobj->started_)
cbk->fireCallback (status, cbk->userarg (), *obj, result, 0);
}
if (cbk_finished && mobj->started_) {
rnsRequestObject* nsreq = (rnsRequestObject *)obj;
nsreq->removeMonitorObject (mobj);
}
}
void
rnsRequestObject::entryCallback (int status, void* arg, rsvcData* data)
{
rnsMonitorObj* mobj = (rnsMonitorObj *)arg;
cdevCallback* cbk = mobj->userCallback_;
cdevRequestObject* obj = mobj->reqObj_;
cdevData result;
int cbk_finished = 1;
// first time this callback is called
if (mobj->tobj_) {
delete mobj->tobj_;
mobj->tobj_ = 0;
}
if (status == RSVC_SUCCESS || status == RSVC_INCOMPLETE) {
rnsRequestObject::dataRsvcToCdev (*data, result);
cbk->fireCallback (RSVC_SUCCESS, cbk->userarg (), *obj, result, 1);
cbk_finished = 0;
if (!mobj->started_)
mobj->started_ = 1;
}
else if (status == RSVC_CBK_FINISHED) {
rnsRequestObject::dataRsvcToCdev (*data, result);
if (mobj->started_)
cbk->fireCallback (status, cbk->userarg (), *obj, result, 0);
}
else {
if (mobj->started_)
cbk->fireCallback (status, cbk->userarg (), *obj, result, 1);
}
if (cbk_finished && mobj->started_) {
rnsRequestObject* nsreq = (rnsRequestObject *)obj;
nsreq->removeMonitorObject (mobj);
}
}
int
rnsRequestObject::monitorOff (rsvcData& data, rnsMonitorObj* mobj)
{
int status;
status = client_->monitorOffValue (_RSVC_CDEV_SERVERS, data,
&(rnsRequestObject::monitorCallback),
(void *)mobj);
return status;
}
int
rnsRequestObject::monitorEntryOff (rnsMonitorObj* mobj)
{
int status;
rsvcData empty;
status = client_->monitorOffIncomingEntries (_RSVC_CDEV_SERVERS, empty,
&(rnsRequestObject::entryCallback),
(void *)mobj);
return status;
}
int
rnsRequestObject::sendNoBlock (cdevData& out, cdevData& result)
{
return sendNoBlock (&out, &result);
}
int
rnsRequestObject::sendNoBlock (cdevData* out, cdevData& result)
{
return sendNoBlock (out, &result);
}
int
rnsRequestObject::sendNoBlock (cdevData& out, cdevData* result)
{
return sendNoBlock (&out, result);
}
int
rnsRequestObject::sendNoBlock (cdevData* out, cdevData* result)
{
if (deferExecution (out, result))
return CDEV_SUCCESS;
int status = CDEV_SUCCESS;
cdevTranObj* xobj = 0;
rnsService* nservice = (rnsService *)service_;
if (client_->connected ()) {
switch (action_) {
case rnsRequestObject::GET:
{
if (out == 0 || result == 0)
return CDEV_INVALIDARG;
xobj = new cdevTranObj (&system_, this, result, 0);
rsvcData outdata;
if (rnsRequestObject::dataCdevToRsvc (*out, outdata) != CDEV_SUCCESS)
status = CDEV_INVALIDARG;
else {
if (client_->getValue (_RSVC_CDEV_SERVERS, outdata,
&(rnsRequestObject::getCallback),
(void *)xobj) != CDEV_SUCCESS)
status = CDEV_IOFAILED;
}
if (status != CDEV_SUCCESS)
delete xobj;
}
break;
default:
status = CDEV_INVALIDARG;
break;
}
}
else
status = CDEV_NOTCONNECTED;
return status;
}
int
rnsRequestObject::send (cdevData& out, cdevData& result)
{
return send (&out, &result);
}
int
rnsRequestObject::send (cdevData* out, cdevData& result)
{
return send (out, &result);
}
int
rnsRequestObject::send (cdevData& out, cdevData* result)
{
return send (&out, result);
}
int
rnsRequestObject::send (cdevData* out, cdevData* result)
{
int status = CDEV_SUCCESS;
rnsService* nservice = (rnsService *)service_;
if (client_->connected ()) {
switch (action_) {
case rnsRequestObject::GET:
if (out == 0 || result == 0)
status = CDEV_INVALIDARG;
else {
cdevGroup grp (2, system_);
grp.start ();
sendNoBlock (out, result);
grp.end ();
grp.pend (4.0);
if (!grp.allFinished ())
status = CDEV_TIMEOUT;
}
break;
case rnsRequestObject::QUERY:
if(out==0 || result==0)
status = CDEV_INVALIDARG;
else {
cdevCallback cb = localQuerySynchronizer::getCallbackObj();
if((status=sendCallback(out, cb))==CDEV_SUCCESS)
{
cdevTimeValue t(5.0);
cdevClock timer;
timer.schedule(NULL, t);
while(!localQuerySynchronizer::cbDone && !timer.expired()) nservice->poll();
if(!localQuerySynchronizer::cbDone) status = CDEV_TIMEOUT;
else *result = localQuerySynchronizer::cbData;
}
}
break;
default:
status = CDEV_INVALIDARG;
break;
}
}
else
status = CDEV_NOTCONNECTED;
return status;
}
int
rnsRequestObject::dataCdevToRsvc (cdevData& data, rsvcData& res)
{
char val[1024];
for (int i = 0; i < rnsRequestObject::numstags_; i++) {
if (data.get (rnsRequestObject::stags_[i], val, sizeof (val))
!= CDEV_SUCCESS)
return CDEV_ERROR;
res.insert (rnsRequestObject::stags_[i], val);
}
return CDEV_SUCCESS;
}
int
rnsRequestObject::dataRsvcToCdev (rsvcData& data, cdevData& res)
{
rsvcDataIterator ite (&data);
int type;
int tag;
size_t numelems;
size_t dim;
char* ctag;
for (ite.init (); !ite ; ++ite) {
ctag = (char *)ite.tag ();
type = data.getType (ctag);
data.getElems (ctag, &numelems);
data.getDim (ctag, &dim);
if (cdevData::tagC2I (ctag, &tag) != CDEV_SUCCESS || dim > 1)
continue;
switch (type) {
case RSVC_BYTE:
case RSVC_INT16:
case RSVC_UINT16:
case RSVC_INT32:
case RSVC_UINT32:
{
if (dim == 0) {
int val;
data.get (ctag, &val);
res.insert (tag, val);
}
else {
int* val = new int[numelems];
data.get (ctag, val);
res.insert (tag, val, numelems);
delete []val;
}
}
break;
case RSVC_FLOAT:
{
if (dim == 0) {
float val;
data.get (ctag, &val);
res.insert (tag, val);
}
else {
float* val = new float[numelems];
data.get (ctag, val);
res.insert (tag, val, numelems);
delete []val;
}
}
break;
case RSVC_DOUBLE:
{
if (dim == 0) {
double val;
data.get (ctag, &val);
res.insert (tag, val);
}
else {
double* val = new double[numelems];
data.get (ctag, val);
res.insert (tag, val, numelems);
delete []val;
}
}
break;
case RSVC_STRING:
{
if (dim == 0) {
char val[1024];
data.get (ctag, val, sizeof (val));
res.insert (tag, val);
}
else {
char** val = new char*[numelems];
data.get (ctag, val);
res.insert (tag, val, numelems);
}
}
break;
default:
break;
}
}
return CDEV_SUCCESS;
}
int
rnsRequestObject::removeMonitorObject (rnsMonitorObj* mobj)
{
rnsService *nservice = (rnsService *)service_;
nservice->removeMonitorObject (mobj);
delete mobj;
return CDEV_SUCCESS;
}
int
rnsRequestObject::findAction (char* msg, int& action)
{
if (strcasecmp (msg, "query") == 0)
action = rnsRequestObject::QUERY;
else if (strcasecmp (msg, "get") == 0)
action = rnsRequestObject::GET;
else if (strcasecmp (msg, "monitorOn") == 0)
action = rnsRequestObject::MONITORON;
else if (strcasecmp (msg, "monitorOff") == 0)
action = rnsRequestObject::MONITOROFF;
else if (strcasecmp (msg, "monitorEntry") == 0)
action = rnsRequestObject::MONITORENTRY;
else if (strcasecmp (msg, "monitorEntryOff") == 0)
action = rnsRequestObject::MONITORENTRYOFF;
else
action = rnsRequestObject::UNKNOWN;
return CDEV_SUCCESS;
}
@@ -0,0 +1,130 @@
//-----------------------------------------------------------------------------
// Copyright (c) 1994,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:
// CDEV Resource Name Service Request Object
//
// Author: Jie Chen
//
//
//
#ifndef _RNS_REQUEST_OBJECT_H
#define _RNS_REQUEST_OBJECT_H
#include <cdevSystem.h>
#include <cdevRequestObject.h>
class rsvcClient;
class rnsService;
class rnsMonitorObj;
class rnsRequestObject: public cdevRequestObject
{
public:
// constructor and destructor
rnsRequestObject (char* device,
char* msg,
rnsService* svc,
cdevSystem& system = cdevSystem::defaultSystem());
~rnsRequestObject (void);
int send (cdevData& out, cdevData& result);
int send (cdevData *out, cdevData& result);
int send (cdevData& out, cdevData* result);
int send (cdevData *out, cdevData* result);
// PURPOSE: Synchronous IO operations
// REQUIRE: When do query and get, result must be provided
// PROMISE: return CDEV_SUCCESS: success.
int sendNoBlock (cdevData& out, cdevData& result);
int sendNoBlock (cdevData* out, cdevData& result);
int sendNoBlock (cdevData& out, cdevData* result);
int sendNoBlock (cdevData* out, cdevData* result);
// PURPOSE: Asynchronous IO operations used in conjunction with
// cdevGroup or system
// REQUIRE:
// PROMISE: return CDEV_SUCCESS: requests have been sent out.
int sendCallback (cdevData& out, cdevCallback& callback);
int sendCallback (cdevData* out, cdevCallback& callback);
// PURPOSE: Asynchromous IO operations with a user supplied callback function
// REQUIRE:
// PROMISE: User callback function will be called with status information
// status = CDEV_DISCONNECTED: channel discconected
// status = CDEV_SUCCESS : everything is OK
// status = CDEV_ERROR : something fishy.
// status = CDEV_INCOMPLETE : data flow will coming (88)
// status = CDEV_CBK_FINISHED: query callback finished (89)
// status = CDEV_QUERYMSG_ERR: query message syntax erro (91)
int getState (void);
// PURPOSE: get connection state
// REQUIRE: none
// PROMISE: CDEV_CONNECTED or CDEV_NOTCONNECTED
const char *className (void) const {return "rnsRequestObject";}
protected:
// find out action from message
static int findAction (char* msg, int& action);
// action value
typedef enum {GET = 0x2000,QUERY,MONITORON,MONITOROFF,
MONITORENTRY, MONITORENTRYOFF, UNKNOWN} RNSENUMVERB;
// get value callback
static void getCallback (int status, void* arg, rsvcData* data);
// query value callback
static void queryCallback (int status, void* arg, rsvcData* data);
// monitor value callback
static void monitorCallback (int status, void* arg, rsvcData* data);
// monitor entry callback
static void entryCallback (int status, void* arg, rsvcData* data);
// data conversion from rsvc to cdev
static int dataRsvcToCdev (rsvcData& data, cdevData& result);
// data conversion from cdev to rsvc
static int dataCdevToRsvc (cdevData& data, rsvcData& result);
// remove a monitor object
int removeMonitorObject (rnsMonitorObj* mobj);
// monitor off a callback
int monitorOff (rsvcData& data, rnsMonitorObj* obj);
// monitor off entry callback
int monitorEntryOff (rnsMonitorObj* obj);
// resend a monitor callback
int sendMonitor (rnsMonitorObj* mobj);
// resend a monitor entry callback
int sendEntryMonitor (rnsMonitorObj* mobj);
private:
// two tags are needed for all serachs
static char* stags_[];
static int numstags_;
// action type
int action_;
// pointer of underlying client connection
rsvcClient* client_;
// friend class
friend class rnsService;
};
#endif
+383
View File
@@ -0,0 +1,383 @@
//-----------------------------------------------------------------------------
// Copyright (c) 1994,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:
// Implementation of nsService Class
//
// Author: Jie Chen
//
// Revision History:
// rnsService.cc,v
// Revision 1.8 1998/03/19 18:31:43 chen
// add monitorEntry capability
//
// Revision 1.7 1998/02/23 16:29:35 chen
// change back to use alarm to handle reconnecton to the name server
//
// Revision 1.6 1998/02/19 18:39:52 akers
// Bug Fixes
//
// Revision 1.5 1998/02/18 14:42:52 chen
// add registerFd to the service
//
// Revision 1.4 1998/02/10 18:06:44 chen
// use system timer instead of alarm
//
// Revision 1.3 1998/02/06 15:11:26 chen
// add connection management for name server
//
// Revision 1.2 1998/01/30 18:31:37 akers
// Ongoing development
//
// Revision 1.1 1998/01/22 17:07:52 akers
// Addition of new NameServer
//
//
//
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#ifndef _WIN32
#include <unistd.h>
#endif
#include "rnsService.h"
#include "rnsRequestObject.h"
#include <rnsMonitorObj.h>
#define _RNS_CLIENT_RECONN_TIMEOUT 5
char * rnsService::tags_[] = {
"table",
"key",
"keyExp",
"keyType",
"name",
"domain",
"host",
"owner",
"time",
"port",
"pid",
"ping",
"client",
"queryMsg"
};
int rnsService::numtags_ = 14;
static rnsService* _rnsNameService_ = 0;
#ifdef _WIN32
void CALLBACK _rnsAlarmHandler_ ( HWND hwnd, UINT umsg, UINT idEvent, DWORD dwTime )
{
if (_rnsNameService_->reconnect () == CDEV_SUCCESS)
{
if (_rnsNameService_->monitorsRestarted ())
{
KillTimer(NULL, idEvent);
}
}
}
#else
static struct sigaction _oldaction_;
static void _rnsAlarmHandler_ (int /* signo */)
{
int done = 0;
if (_rnsNameService_->reconnect () == CDEV_SUCCESS) {
if (_rnsNameService_->monitorsRestarted ()) {
sigaction (SIGALRM, &_oldaction_, 0);
done = 1;
}
}
if (!done)
alarm (_RNS_CLIENT_RECONN_TIMEOUT);
}
#endif
rnsService::rnsService (char* name, cdevSystem& system)
:cdevService (name, system), client_ (), fds_ (0), numFds_ (0),
monobjs_ ()
{
#ifdef _TRACE_OBJECTS
printf (" Create rnsService Class Object\n");
#endif
// register all tags
for (int i = 0; i < rnsService::numtags_; i++)
cdevData::addTag (rnsService::tags_[i]);
// remember this service
_rnsNameService_ = this;
}
rnsService::~rnsService (void)
{
#ifdef _TRACE_OBJECTS
printf (" Delete rnsService Class Object\n");
#endif
if (client_.connected ())
client_.disconnect ();
if (numFds_ > 0)
delete []fds_;
// delete all callbacks
cdevSlistIterator ite (monobjs_);
rnsMonitorObj* mobj = 0;
for (ite.init (); !ite; ++ite) {
mobj = (rnsMonitorObj *) ite ();
delete mobj;
}
}
int
rnsService::getFd (int* &fd, int& numFd)
{
fd = fds_;
numFd = numFds_;
return CDEV_SUCCESS;
}
int
rnsService::flush (void)
{
return CDEV_SUCCESS;
}
int
rnsService::poll (void)
{
return client_.pendIO (0.001);
}
int
rnsService::pend (int /* fd */)
{
return client_.pendIO ();
}
int
rnsService::pend (double seconds, int)
{
return client_.pendIO (seconds);
}
int
rnsService::getRequestObject (char* deviceName, char* msg,
cdevRequestObject* &req)
{
if (!client_.connected ()) {
char* nsHost = getenv ("CDEV_NAME_SERVER");
if (!nsHost) {
reportError (CDEV_SEVERITY_SEVERE, serviceName_, 0,
"Cannot find environment variable CDEV_NAME_SERVER !!!");
req = 0;
return CDEV_ERROR;
}
if (client_.connect (nsHost, RSVC_SERVER_PORT, 3.0) != RSVC_SUCCESS) {
reportError (CDEV_SEVERITY_SEVERE, serviceName_, 0,
"Cannot connect to name server at port %d on %s",
RSVC_SERVER_PORT, nsHost);
req = 0;
return CDEV_ERROR;
}
if (numFds_ > 0)
delete []fds_;
fds_ = new int[1];
numFds_ = 1;
fds_[0] = client_.getFd ();
// register fd to the system
registerFd (client_.getFd (), 1);
// register a disconnection callback
if (client_.disconnectCallback (&(rnsService::discCallback),
(void *)this) != RSVC_SUCCESS)
reportError (CDEV_SEVERITY_WARN, serviceName_, 0,
"Cannot register disconnect callback");
}
req = new rnsRequestObject (deviceName, msg, this, system_);
return CDEV_SUCCESS;
}
int
rnsService::reconnect (void)
{
char* nsHost = getenv ("CDEV_NAME_SERVER");
if (!client_.connected ()) {
if (client_.connect (nsHost, RSVC_SERVER_PORT, 3.0) == RSVC_SUCCESS) {
reportError (CDEV_SEVERITY_INFO, serviceName_, 0,
"Reconnected to name server at port %d on %s",
RSVC_SERVER_PORT, nsHost);
fds_ = new int[1];
numFds_ = 1;
fds_[0] = client_.getFd ();
// register this fd to the sysem
registerFd (client_.getFd(), 1);
// register a disconnection callback
if (client_.disconnectCallback (&(rnsService::discCallback),
(void *)this) != RSVC_SUCCESS)
reportError (CDEV_SEVERITY_WARN, serviceName_, 0,
"Cannot register disconnect callback");
return CDEV_SUCCESS;
}
else
return CDEV_TIMEOUT;
}
return CDEV_SUCCESS;
}
int
rnsService::getNameServer (cdevDevice* &ns)
{
ns = 0;
return CDEV_SUCCESS;
}
cdevService *
newRnsService (char* name, cdevSystem* system)
{
return new rnsService (name, *system);
}
int
rnsService::addMonitorObject (rnsMonitorObj* obj)
{
cdevSlistIterator ite (monobjs_);
rnsMonitorObj* mobj = 0;
for (ite.init (); !ite; ++ite) {
mobj = (rnsMonitorObj *) ite ();
if (*(mobj->userCallback_) == *(obj->userCallback_))
return CDEV_ERROR;
}
monobjs_.add ((void *)obj);
return CDEV_SUCCESS;
}
int
rnsService::removeMonitorObject (rnsMonitorObj* obj)
{
cdevSlistIterator ite (monobjs_);
rnsMonitorObj* mobj = 0;
int found = 0;
for (ite.init (); !ite; ++ite) {
mobj = (rnsMonitorObj *) ite ();
if (mobj == obj) {
found = 1;
break;
}
}
if (found) {
monobjs_.remove ((void *)obj);
return CDEV_SUCCESS;
}
return CDEV_ERROR;
}
rnsMonitorObj*
rnsService::hasCallback (cdevCallback& cbk)
{
cdevSlistIterator ite (monobjs_);
rnsMonitorObj* mobj = 0;
for (ite.init (); !ite; ++ite) {
mobj = (rnsMonitorObj *) ite ();
if (*(mobj->userCallback_) == cbk)
return mobj;
}
return 0;
}
int
rnsService::monitorsRestarted (void)
{
cdevSlistIterator ite (monobjs_);
rnsMonitorObj* mobj = 0;
rnsRequestObject* req = 0;
int notdone = 0;
for (ite.init (); !ite; ++ite) {
mobj = (rnsMonitorObj *)ite ();
if (!mobj->started_) {
notdone = 1;
req = (rnsRequestObject *)mobj->reqObj_;
if (req->action_ == rnsRequestObject::MONITORON)
req->sendMonitor (mobj);
else if (req->action_ == rnsRequestObject::MONITORENTRY)
req->sendEntryMonitor (mobj);
}
}
return !notdone;
}
void
rnsService::discCallback (int /* status */, void* arg, rsvcData* /* data */)
{
rnsService* nsvc = (rnsService *) arg;
if (nsvc->numFds_ > 0) {
// remove this fd from the system
for (int i = 0; i < nsvc->numFds_; i++)
nsvc->registerFd (nsvc->fds_[i], 0);
delete [](nsvc->fds_);
nsvc->numFds_ = 0;
}
cdevSlistIterator ite (nsvc->monobjs_);
rnsMonitorObj* mobj = 0;
cdevCallback* cbk = 0;
cdevRequestObject *req = 0;
cdevData empty;
for (ite.init (); !ite; ++ite) {
mobj = (rnsMonitorObj *) ite ();
cbk = mobj->userCallback_;
req = mobj->reqObj_;
cbk->fireCallback (CDEV_DISCONNECTED, cbk->userarg (),
*req, empty, 0);
mobj->started_ = 0;
}
#ifdef _WIN32
SetTimer (NULL, 0, 1000*_RNS_CLIENT_RECONN_TIMEOUT, _rnsAlarmHandler_);
#else
// register a alarm handler to try to connect to the name server
struct sigaction act;
act.sa_handler = _rnsAlarmHandler_;
sigemptyset (&act.sa_mask);
act.sa_flags = 0;
if (sigaction (SIGALRM, &act, &_oldaction_) < 0)
cdevSystem::defaultSystem().reportError(
CDEV_SEVERITY_ERROR, "RNS Service", NULL,
"Cannot register alarm signal handler");
else
alarm (_RNS_CLIENT_RECONN_TIMEOUT);
#endif
}
+128
View File
@@ -0,0 +1,128 @@
//-----------------------------------------------------------------------------
// Copyright (c) 1994,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:
// Implementation of cdev interface to resouce service client
//
// This is only a subset of whole APIs of rsvc client
//
// Author: Jie Chen
//
//
//
#ifndef _NS_SERVICE_H
#define _NS_SERVICE_H
#ifndef _CDEV_MANAGE_SERVERS
#define _CDEV_MANAGE_SERVERS
#endif
#include <stdio.h>
#include <string.h>
#include <cdevService.h>
#include <cdevRequestObject.h>
#include <cdevSlist.h>
#include <rsvcClient.h>
#include <rsvcSpec.h>
extern "C" RSVCAPI cdevService * newRnsService (char* name, cdevSystem* system);
class rnsMonitorObj;
class rnsRequestObject;
class rnsService: public cdevService
{
public:
// cornstructor
rnsService (char* name, cdevSystem& system = cdevSystem::defaultSystem ());
int getFd (int * &fd, int &numFd);
// PURPOSE: return channel access network file descriptors
// REQUIRE: callers provide pointer only and don't free memory
// PROMISE: numFd will be real number of file descriptors of the
// channel access client. return 0: always
int flush (void);
// PURPOSE: flush network requests
// REQUIRE: nothing
// PROMISE: return CDEV_SUCCESS: success
int poll (void);
// PURPOSE: polling method
// REQUIRE: nothing
// PROMISE: return CDEV_SUCCESS: success. Else error
int pend (int fd = -1);
// PURPOSE: handle network pending
// REQUIRE: nothing
// PROMISE: return CDEV_SUCCESS: success, else error
int pend (double seconds, int fd = -1);
// PURPOSE: handle network pending for 'seconds'
// REQUIRE: nothing
// PROMISE: return 0: success. return CDEV_TIMEOUT for timeout
int getRequestObject (char *deviceName, char *msg,
cdevRequestObject * &req);
// PURPOSE: return a rnsRequestObject (called from attachPtr function
// of cdevRequestObject class)
// REQUIRE: right pair of deviceName and msg.
// PROMISE: a rnsRequestObject
int getNameServer (cdevDevice* &rns);
// PURPOSE: retrieve ca name server in case of missing DDL
// REQUIRE: nothing
// PROMISE:
int monitorsRestarted (void);
// PURPOSE: check whether all monitors have been restarted or not
// REQUIRE: nothing
// PROMISE: 1: yes, 0: no
int reconnect (void);
// PURPOSE: reconnect to name server
// REQUIRE: nothing
// PROMISE: CDEV_SUCCESS on sucessful connection
const char* className (void) const {return "rnsService";}
protected:
// deny direct access to destructor
~rnsService (void);
// add a monitor object
int addMonitorObject (rnsMonitorObj* obj);
// remove a monitor object
int removeMonitorObject (rnsMonitorObj* obj);
// check whether this callback is in the list
rnsMonitorObj* hasCallback (cdevCallback& cbk);
// server disconnection callback
static void discCallback (int status, void* arg, rsvcData* data);
private:
rsvcClient client_;
int *fds_;
int numFds_;
// list of monitor object
cdevSlist monobjs_;
// all tags needed for this service
static char* tags_[];
// number of tags needed for this service
static int numtags_;
// friend class
friend class rnsRequestObject;
};
#endif

Some files were not shown because too many files have changed in this diff Show More