Hyrax: Server Side Functions: Difference between revisions
Line 27: | Line 27: | ||
=== The <code>helloWorld()</code> function === | === The <code>helloWorld()</code> function === | ||
Here is the <font size="2"><code>example_ssf::helloWorld()</code></font> function from [https://scm.opendap.org/svn/trunk/example_ssFunction/ the example_ssFunction project.] The <font size="2"><code>example_ssf::helloWorld()</code></font> function is defined in the file [https://scm.opendap.org/svn/trunk/example_ssFunction/ExampleServerSideFunctions.cc ExampleServerSideFunctions.cc]. | Here is the <font size="2"><code>example_ssf::helloWorld()</code></font> function from [https://scm.opendap.org/svn/trunk/example_ssFunction/ the example_ssFunction project.] The <font size="2"><code>example_ssf::helloWorld()</code></font> function is defined in the file [https://scm.opendap.org/svn/trunk/example_ssFunction/ExampleServerSideFunctions.cc ExampleServerSideFunctions.cc]. | ||
Line 40: | Line 39: | ||
We can see from the method's type signature that it is a BaseType function. The <font size="2"><code>helloWorld()</code></font> function creates a DAP String object, set it's value and return via the return value parameter '''btpp'''. | We can see from the method's type signature that it is a BaseType function. The <font size="2"><code>helloWorld()</code></font> function creates a DAP String object, set it's value and return via the return value parameter '''btpp'''. | ||
=== A child class of libdap::Function === | |||
Now we need a <font size="2"><code>libdap::Function</code></font> to provide an API by which the server can learn things about our new function. Here is the <font size="2"><code>example_ssf::HelloWorld</code></font> class as defined in [https://scm.opendap.org/svn/trunk/example_ssFunction/ExampleServerSideFunctions.h ExampleServerSideFunctions.h]. | Now we need a <font size="2"><code>libdap::Function</code></font> to provide an API by which the server can learn things about our new function. Here is the <font size="2"><code>example_ssf::HelloWorld</code></font> class as defined in [https://scm.opendap.org/svn/trunk/example_ssFunction/ExampleServerSideFunctions.h ExampleServerSideFunctions.h]. | ||
Line 68: | Line 67: | ||
=== A child class of BESAbstractModule === | |||
In order to get our new function into Hyrax we need to have the BES load it at startup. This is done by writing a very simple BES module. For this example our module classed is called <font size="2"><code>ExampleServerSideFunctions</code></font> which is declared in the header file [https://scm.opendap.org/svn/trunk/example_ssFunction/ExampleServerSideFunctions.h ExampleServerSideFunctions.h]: | In order to get our new function into Hyrax we need to have the BES load it at startup. This is done by writing a very simple BES module. For this example our module classed is called <font size="2"><code>ExampleServerSideFunctions</code></font> which is declared in the header file [https://scm.opendap.org/svn/trunk/example_ssFunction/ExampleServerSideFunctions.h ExampleServerSideFunctions.h]: |
Revision as of 22:31, 11 February 2013
Overview
Before you embark upon writing a server side function DAP2 you should read through this overview of DAP2 constraint expressions and their use of functions
Types of Server Side Functions
- BaseType Functions
- void(*btp_func)(int argc, libdap::BaseType *argv[], libdap::DDS &dds, libdap::BaseType **btpp)
- A BaseType function takes four arguments: an integer (argc), a vector of BaseType *s (argv), the DDS for the dataset for which these function is being evaluated (analogous to the ENVP in UNIX) and a pointer for the function's return value. ARGC is the length of ARGV.
- Boolean Functions
- void(*bool_func)(int argc, libdap::BaseType *argv[], libdap::DDS &dds, bool *result)
- A boolean function takes four arguments, an integer (argc), a vector of BaseType *s (argv), the DDS for the dataset for which these function is being evaluated (analogous to the ENVP in UNIX) and a pointer for the function's return value. ARGC is the length of ARGV.
- Projection Functions
- void(*proj_func)(int argc, libdap::BaseType *argv[], libdap::DDS &dds, libdap::ConstraintEvaluator &ce)
- A projection function is a function that appears in the projection part of the CE and is executed for its side-effect. Usually adds a new variable to the DDS. These are run _during the parse_ so their side-effects can be used by subsequent parts of the CE.
Writing Server Side Functions
- What we'll do
- Write a C++ function which uses one of the three server function type signatures
- Write a very simple subclass of the
libdap::Function
class and install the your function into the class using thelibdap::Function.setFunction()
method. - Write a very simple subclass of the
BESAbstractModule
and in theinitialize()
method, add an instance of your Function class to thelibdap::ServerFunctionsList
- Build and install the module.
The helloWorld()
function
Here is the example_ssf::helloWorld()
function from the example_ssFunction project. The example_ssf::helloWorld()
function is defined in the file ExampleServerSideFunctions.cc.
void helloWorld( int argc, libdap::BaseType *argv[], libdap::DDS &dds, libdap::BaseType **btpp)
{
Str *dapResult = new Str("helloWorldFunction_result");
dapResult->set_value("Howdy Stranger...");
*btpp = dapResult;
}
We can see from the method's type signature that it is a BaseType function. The helloWorld()
function creates a DAP String object, set it's value and return via the return value parameter btpp.
A child class of libdap::Function
Now we need a libdap::Function
to provide an API by which the server can learn things about our new function. Here is the example_ssf::HelloWorld
class as defined in ExampleServerSideFunctions.h.
class HelloWorldFunction: public libdap::ServerFunction {
public:
HelloWorldFunction()
{
setName("helloWorld");
setDescriptionString("Returns a DAP String object whose value is the string 'Hello World'.");
setUsageString("helloWorld()");
setRole("http://services.opendap.org/dap4/server-side-function/hellowWorld");
setDocUrl("http://docs.opendap.org/index.php/Hyrax:_Server_Side_Functions");
setFunction(example_ssf::helloWorld);
setVersion("1.0");
}
virtual ~HelloWorldFunction()
{
}
};
The parent class of our new example_ssf::HelloWorld
class is libdap::Function
. Since libdap::Function
is not an abstract we don't need to override any methods to make the child class work, all we do is give the child class state that's specific to our new function.
Now we have a function, and a class through whose API we can learn about our function. Now we just need to hook it up to the BES and Hyrax...
A child class of BESAbstractModule
In order to get our new function into Hyrax we need to have the BES load it at startup. This is done by writing a very simple BES module. For this example our module classed is called ExampleServerSideFunctions
which is declared in the header file ExampleServerSideFunctions.h:
class ExampleServerSideFunctions: public BESAbstractModule {
public:
ExampleServerSideFunctions() {}
virtual ~ExampleServerSideFunctions() {}
virtual void initialize(const string &modname);
virtual void terminate(const string &modname);
virtual void dump(ostream &strm) const;
};
and implemented in ExampleServerSideFunctions.cc
void ExampleServerSideFunctions::initialize(const string &modname) {
BESDEBUG( "ExampleServerSideFunctions", "Initializing ExampleServerSideFunctions:" << endl );
libdap::ServerFunctionsList::TheList()->add_function(new example_ssf::HelloWorldFunction());
BESDEBUG( "ExampleServerSideFunctions", "Done initializing ExampleServerSideFunctions" << endl );
}
void ExampleServerSideFunctions::terminate(const string &modname) {
BESDEBUG( "ExampleServerSideFunctions", "Removing ExampleServerSideFunctions module (this does nothing)." << endl );
}
extern "C" {
BESAbstractModule *maker() {
return new ExampleServerSideFunctions;
}
}
Note carefully the method ExampleServerSideFunctions.initialize()
which contains the call to the libdap:ServerFunctionsList.addFunction()
method. It is this call that causes a HelloWorld class instance and thus the helloWorld() function to be registered in BES.