Table of Contents
In this exercise, you will create a new Driver component. This component is very simple, and basically only uses other components (it also provides a GoPort). If you're working in an environment in which components are already available that do most of what you need, it is often sufficient to create a component, which we refer to generically as a driver, that orchestrates these existing components to perform your computation.
Unlike other component models (e.g. Cactus or ESMF) CCA does not impose a built-in execution model. CCA allows the user to determine how the components are to be used. The driver component, in essence, takes the place of the main program in a normal application.
In this section we will walk through the construction of a driver
component, either in Fortran (SIDL name
drivers.F90Driver) or C++ (SIDL name
drivers.CXXDriver) Regardless of language, our
driver component will use an
integrator.IntegratorPort (defined in
). It will
also provide a
$STUDENT_SRC/ports/sidl/integrator.sidlgov.cca.ports.GoPort that allows an
outside entity (a user or script) to start execution of the
component. (These ports should be familiar from Chapter 2, Assembling and Running a CCA Application.)
![]() |
Important |
|---|---|
|
This and subsequent exercises use the
You'll need to build the If you are participating in an organized tutorial your account information handout will tell you where you can obtain the tar file on the system you're using instead of having to download it. |
The first step in creating a new component is to create its .sidl file. In SIDL, a component is a
class that implements several SIDL
interfaces. All CCA components must implement the
gov.cca.Component interface, which is
defined as part of the CCA specification (the CCA specification uses
the gov.cca namespace). In addition, components must implement the
interfaces corresponding to any CCA ports they wish to
provide. The CCA specification defines a few
ports, such as gov.cca.ports.GoPort,
but mostly, ports are defined by the people who write components, or
by communities that get together to agree on “standard”
interfaces.
In order to better understand what is required to implement a given
interface, you need to find the SIDL specification for it. First,
we'll look in the SIDL file for the CCA specification to see what the
gov.cca.Component interface looks like.
View . First, notice the package
declarations at the beginning of the file:
CCA_TOOLS_ROOT/share/cca-spec-babel-0_8_0-babel-1.0.0/cca.sidl
package gov {
package cca version 0.8.0 {
...
which declare the gov.cca namespace
for everything in the file.
Now, search for “interface Component”:
... /** * All components must implement this interface. */ interface Component { ... Comments elided ... void setServices(in Services services) throws CCAException; } ...
Which tells us that our driver will have to implement a
setServices. This is the key method that
allows a piece of code to become a CCA component. The component's
setServices method is invoked by the CCA
framework when the component is instantiated, and advertises to the
framework the ports the component will provide
and use.
Since the port this component provides is also
part of the CCA specification, this is the place to look for the
definition of the GoPort. Search for
“interface GoPort”:
... package ports { /** * Go, component, go! */ interface GoPort extends Port { ... Comments elided ... int go(); } ...
First, notice that there is an additional package
declaration here, making the full name of this interface
gov.cca.ports.GoPort. This
definition tells us that our driver component must also implement a
go method.
Now you have enough information to write the SIDL declaration for your driver component. At this point, you should choose whether you want to implement your driver component in C++ or Fortran 90. (Once you get one done, you can implement the other too, if you wish.)
Edit the file
and type in one of the two following SIDL declarations, according to
your choice of language:
$STUDENT_SRC/components/sidl/drivers.sidl
package drivers version 1.0 {
class F90Driver implements gov.cca.ports.GoPort,
gov.cca.Component
{
int go();
void setServices(in gov.cca.Services services)
throws gov.cca.CCAException;
}
}
package drivers version 1.0 {
class CXXDriver implements gov.cca.ports.GoPort,
gov.cca.Component
{
int go();
void setServices(in gov.cca.Services services)
throws gov.cca.CCAException;
}
}
First, notice that the two declarations are identical except for the name, and in reality, you could choose anything you wanted for the name. The only reason we put an indication of the implementation language into the class name of this component was pedagogical: to avoid a name collision if you want to eventually implement both versions, and identify what distinguishes them. Normally, you might want different implementations of a component if they do things differently (i.e. use different algorithms), or in the case of a driver, solve different problems. Under normal circumstances, there is no reason to have more than one implementation of a component that does precisely the same thing (though it is common to have multiple implementations that do things in somewhat different ways, but with the same result).
Second, notice that the class definition references both
gov.cca.ports.GoPort and
gov.cca.Component, and declares all
of the methods that we saw in those interface definitions, with
precisely the same signatures.
Now you need to modify the Makefile system so
that it is aware of the new component you're adding (the drivers.sidl
is already listed there along with other .sidl files).
Edit
and make the following additions:
$STUDENT_SRC/component/MakeIncl.components
# SIDL files containing component declarations
# For example:
# SIDL_FILES = sidl/drivers.sidl
SIDL_FILES = sidl/functions.sidl sidl/integrators.sidl sidl/randomgens.sidl \
sidl/drivers.sidl sidl/unitdrivers.sidl sidl/library.sidl
# The COMPONENTS list contains the fully-qualified names of the component
# classes, augmented with -LANGUAGE, where LANGUAGE is the language
# in which the component is implemented, e.g., c, cxx, f90.
# For example:
# COMPONENTS = drivers.F90Driver-f90 drivers.CXXDriver-cxx
COMPONENTS = drivers.PYDriver-python functions.PiFunction-cxx \
library.CxxUnitsLibraryComp-cxx library.PyUnitsLibraryComp-python \
undrivers.PyDriver-python \
functions.LinearFunction-c integrators.MonteCarlo-f90 \
randomgens.RandNumGenerator-cxx integrators.Trapezoid-cxx \
integrators.Simpson-f77\
drivers.CXXDriver-cxx
Of course if you've chose to create the Fortran 90 driver, you
should add drivers.F90Driver-f90 to the
definition of COMPONENTS instead. In
both cases, notice the backslash
(“\”) used to continue definition on
to the next line. make will accept long lines,
but the files are easier to read if they're nicely formatted.
![]() |
Important |
|---|---|
|
Before proceeding, you need to be sure that you have done the
initial build of the |
When it is processing a .sidl file, Babel needs to be able to
resolve external references contained within the file (for example,
to gov.cca.Component, or to other ports, etc.). The simplest way to do
this is to have Babel collect all of the information it needs in a
repository. The build system for the tutorial
is designed to do this, so at this point, we need to add the new
drivers.sidl file to the repository.
In the
directory, type $STUDENT_SRC/componentsmake .repository to make
Babel process the .sidl files
and update the XML repository. The output should look something
like this:
touch .sidl
### Generating XML for SIDL packages containing component declarations
/san/cca/cca-tools_gcc_intelF90_PIC/bin/babel -t xml -R../xml_repository \
-R/san/cca/cca-tools_gcc_intelF90_PIC/share/ \
cca-spec-babel-0_8_0-babel-1.0.0/xml \
-o ../xml_repository sidl/functions.sidl sidl/integrators.sidl \
sidl/randomgens.sidl sidl/drivers.sidl sidl/unitdrivers.sidl \
sidl/library.sidl
Babel: Parsing URL "file:/san/homedirs/bernhold/student-src/ \
components/sidl/functions.sidl".
Babel: Parsing URL "file:/san/homedirs/bernhold/student-src/ \
components/sidl/integrators.sidl".
Babel: Parsing URL "file:/san/homedirs/bernhold/student-src/ \
components/sidl/randomgens.sidl".
Babel: Parsing URL "file:/san/homedirs/bernhold/student-src/ \
components/sidl/drivers.sidl".
Babel: Parsing URL "file:/san/homedirs/bernhold/student-src/ \
components/sidl/unitdrivers.sidl".
Babel: Parsing URL "file:/san/homedirs/bernhold/student-src/ \
components/sidl/library.sidl".
touch .repository
The next step is to implement the internals of the component, which
are obviously dependent on the implementation language you've
chosen. For C++, continue directly on with Section 3.2, “Implementation of the CXXDriver in C++”. For Fortran 90, please jump to Section 3.3, “Implementation of the F90Driver in
Fortran 90”.