Post on 11-Jan-2016
Grail
Interface and CodeRamón Creager
What is Grail?
• Like the Roman god Janus, Grail provides two faces to two different worlds: From the outside, a SOAP interface to the GBT M&C System. From the M&C perspective, it is an Ygor client:
SOAP
Requests
Callbacks
Ygor (RPC++)
PanelRemote
Monitor
Recipient
Lifetime of a Grail Request
Start
Make connection
Devicefound?
Pass requestTo Device
Return results
Close connection
Create newDeviceClient
Devicecreated?
Return error
Place DeviceIn Map
End
• Grail requests are made to devices, which include managers, sub-managers, coordinators, etc. These are specified by major.minor name format.
• Monitor requests are made to the device that hosts the sampler
• Connections to Grail currently share the lifetime of the requests; that is, every new request creates a new connection.
No
Yes
No
Yes
Lifetime of a Grail Callback
Start
Process M&C callback
Registered?
Open connectionTo Client SOAP
ServerClose connection
Service M&C req. (recipient)
No
Yes
NoYesConnection
success?
Encode andTransmit param
Or sampler.
Unregister all callbacks that use this SOAP
client.
Schedule callback client for deletion.
• Grail callbacks are registered and unregistered through a Grail Request.
• Grail callbacks are handled by the RPC++/M&C task.
• Currently, all parameters for a particular device are registered automatically with the M&C device for Manager callbacks to Grail. Registering a parameter only extends the callback to the client.
• Unlike parameters, samplers are not registered with the Manager unless registered by the Grail Client.
• Parameters should follow the sampler convention to reduce overhead at the Manager level.
Some remaining Grail functional issues
• Grail registers all a manager’s parameters for callbacks. Perhaps these should be registered as needed by the client.
• Some parameters returned incorrectly the very first time they are accessed.
• Grail does not return parameter flags and a time-stamp with the parameter/sampler structures.
• Grail does not currently accept entire parameter structures. Parameters must be set field by field.
• Thread synchronization issues remain between the two Grail threads. Addressing these would improve Grail reliability.
• PanelRemote deadlock issue.
• Grail is a Solaris application, will not work as written under Linux due to RPC++ and threading issues. Also, it cannot be properly compiled by the Linux hosted Solaris cross-compiler.
Grail Application Architecture
Grail
gSOAP server task
GBT M&C
DeviceClient Collection
SOA
P
Grail Client
Recipient/Monitor task
gSOAP client
RPC
SOA
P
RPC
SOAP serverSOAP client
DeviceClientDeviceClient
DeviceClientDeviceClient
The Code
• Grail is written in 100% pure C++
• Grail relies heavily on the gSOAP code generator for its SOAP interfaces
• Grail relies heavily on Ygor for M&C interfaces
• Grail is found in the CVS repository at: ygor/user/Grail
• ≈20% of Grail code is hand coded, the rest is generated by the gSOAP code generator.
Grail directory structure
• Grail is the main source directory. Grail is compiled from this directory.
• DeviceClient hosts the DeviceClient, GenericRecipient and Parameter classes. These could reside in Grail but have their own directory for historical reasons.
• Grail-RPC contains grailstatus.x. rpcgen is run on this file, and the generated code needed by grail copied to Grail.
• Grail-gSOAP contains the gSOAP interface definition file Grail.h. soapcpp2 is run on this file to generate the SOAP server code, and the needed code is copied to Grail.
• GrailCB-gSOAP contains the gSOAP interface definition file GrailCB.h. Like Grail-gSOAP, but defines the callback client interface.
• Env-gSOAP contains env.h, the gSOAP interface definition file that generates the code common to the Server and Client.
ygor/user/Grail
Grail
DeviceClient
Grail-RPC
Grail-gSOAP
GrailCB-gSOAP
Env-gSOAP
sparc-solaris
sparc-solaris
SOAP, and gSOAP
• Why SOAP?
– SOAP (Simple Object Access Protocol) is an XML and text based RPC and Messaging protocol.
– Because of this, it is language and architecture neutral. Libraries for SOAP exist for all major programming languages. Giving the M&C system a SOAP portal opens up the M&C system to user level programming on any architecture using any language with a SOAP library.
• Why gSOAP?
– gSOAP is an Open Source SOAP toolkit for C/C++. It is SOAP 1.1 compliant and is exceptionally well supported and complete. It has a fairly large user community with an active mailing list.
– gSOAP is part library, part code generator. The code generator handles enough of the SOAP details that one could conceivably make use of it without actually understanding SOAP.
– Grail was written in C++ because the M&C system interface consists of a library of C++ classes. Thus gSOAP was a natural tool to use for Grail.
Calc, a simple gSOAP example
SOAP calc server
Add(a, b)Subtract(a, b)Sqrt(a)
SOAP calc client
Concept:
XML
gSOAP input (calc.h):
//gsoap ns schema namespace: urn:calc
typedef double xsd__double;typedef char *xsd__string;
int ns__add(xsd__double a, xsd__double b, xsd__double &result);int ns__sub(xsd__double a, xsd__double b, xsd__double &result);int ns__sqrt(xsd__double a, xsd__double &result);
Calc, a simple gSOAP example (continued)
I:\rc\gSOAPexamples\calc_server\temp\\samba-gb\rcreager $soapcpp2 calc.h
** The gSOAP Stub and Skeleton Compiler for C and C++ 2.3 rev 3** Copyright (C) 2001-2003 Genivia inc. & FSU. All Rights Reserved.** This product is provided "as is", without any warranty
Saving soapStub.hSaving soapH.hSaving soapC.cppSaving soapClient.cppSaving soapServer.cppSaving soapClientLib.cppSaving soapServerLib.cppSaving ns.wsdl Web Service descriptionSaving soapProxy.h client proxySaving soapObject.h server objectSaving ns.add.req.xml sample SOAP/XML requestSaving ns.add.res.xml sample SOAP/XML responseSaving ns.sub.req.xml sample SOAP/XML requestSaving ns.sub.res.xml sample SOAP/XML responseSaving ns.sqrt.req.xml sample SOAP/XML requestSaving ns.sqrt.res.xml sample SOAP/XML responseSaving ns.nsmap namespace mapping tableSaving ns.xsd XML schema description
Compilation successful
Calc, a simple gSOAP example: Server functionsint ns__add(struct soap *se, double a, double b, double &result){ result = a + b; return SOAP_OK;}
int ns__sub(struct soap *se, double a, double b, double &result){ result = a - b; return SOAP_OK;}
int ns__sqrt(struct soap *se, double a, double &result){ if (a >= 0) { result = sqrt(a); return SOAP_OK; } else { soap_fault(se); se->fault->faultstring = "Square root of negative number"; se->fault->detail = "I can only take the square root of a non-negative number"; return SOAP_FAULT; }}
Calc, a simple gSOAP example: Server loop#include "soapH.h"
int main(int /*argc*/, char **/*argv*/){ struct soap se; int m, s; // master and slave sockets char name[200];
soap_init(&se); gethostname(name, 199); m = soap_bind(&se, name, 18083, 100); if (m < 0) { soap_print_fault(&se, stderr); return -1; } while (1) { s = soap_accept(&se); if (s < 0) { soap_print_fault(&se, stderr); return -1; } soap_serve(&se); // process RPC skeletons soap_end(&se); // clean up everything and close socket }}
Calc, a simple gSOAP example: Client
#include "soapH.h"
int main(int argc, char **argv)
{ soap se; double a, b, result = 0; char host[300];
snprintf(host, 299, "http://%s:18083", argv[1]); a = atof(argv[2]); b = atof(argv[3]);
soap_init(&se);
if (soap_call_ns__add(&se, host, "", a, b, result) != SOAP_OK) { soap_print_fault(&se, stderr); }
return 1;
}
Calc, a simple gSOAP example: on the wire
<?xml version="1.0" encoding="UTF-8"?><SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns="http://titan:18083"> <SOAP-ENV:Body id="_0" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <ns:add> <a xsi:type="xsd:double">2.0</a> <b xsi:type="xsd:double">3.0</b> </ns:add> </SOAP-ENV:Body></SOAP-ENV:Envelope>
<?xml version="1.0" encoding="UTF-8"?><SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns="http://titan:18083"> <SOAP-ENV:Body id="_0" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <ns:addResponse> <result xsi:type="xsd:double">5.0</result> </ns:addResponse> </SOAP-ENV:Body></SOAP-ENV:Envelope>
Grail Device Classes
DeviceClientMap DeviceClient*
PanelRemote
GenericRecipientRecipient
RecipientServerMonitor 1
1
1
_parameter: std::vector<Parameter>
operator[]() _sampler: std::vector<Parameter>
Parameter::Visitor
DeviceClient::Callback
ParameterToSoapVisitor
GrailCallback0..n
Operator()()