CCA Compliant HPC++ Components for CCAT


Introduction

Components are software objects that provide implementations of a set of standard behaviors. These behaviors are defined by the component framework to ensure that components can be composed and interoperate efficiently and without conflict. The framework that we have developed conforms to the specification provided by the CCA Forum . The framework implementation uses HPC++ as its runtime mechanism. We hereby explain the process of "componentizing" (converting to a component) your code by means of a simple example.

A Simple Example

I believe the best way to explain the CCAT component structure is by way of a simple example. As I walk through the process of developing this component, you will be introduced to some fundamental concepts in component based distributed computing like ports , port-compatibility , naming , events , stubs and skeletons . Please make sure you understand these before proceeding further. Lets assume you need to develop two components: Newstring and Concat . As the names suggest, Newstring component generates a new string and Concat concatenates the strings that it receives. The aim of this example is to develop these two into CCA compliant CCAT components so that we can connect the two and steer the process of string-generation and concatenation. In order to tie these two components together we need to connect their ports .

Ports

The Port is a fundamental CCA concept. A port represents the connection endpoint for a component. Two ports that are compatible can be connected and serve as the communication channel between components. A port could be either a provides port or a uses port . A provides port can be viewed as a service that is provided to other components. A uses port can be thought of as a connection to the surface of the component. To a component developer a uses port provides the interface that the component wants to use. Ports are specified in Interface Definition Language (IDL) . The CCAT-team is working towards adopting the Scientific Interface Definition Language (SIDL) for port specification.

IDL Specification

IDL is a high-level language used to specify the interfaces that a component wants to expose to the outer world. We now introduce you to the actual IDL specification that we need for the NewString component. However to add an epsilon amount of complexity to the example, our string churner spits out MyString object in each iteration instead of just a string. MyString object holds some mundane information apart from a character string, details of which aren't relevant to our purpose of illustrating the componentizing process.

// File: MyString.idl
// This is a specification in IDL
// for the port of type MyString

interface MyString : Port {
   int replyValue sendString(MyString myOwnString);
};

// End of file MyString.idl

Stub Compiler

The object oriented paradigm of the high performance class library, HPC++, makes it ideal for use as the underlying run time system for our framework. The remote method invocations need to be marshalled on the client side and appropriately unmarshalled on the server side. The user should not be bogged down by the low level details of the wire protocol and different run time systems that (s)he plans to interact with. This motivated us to develop a stub compiler that can parse the IDL specification as above and automatically generate the necessary code to facilitate in the efficient use of the elegant runtime system lying underneath the framework. A user may intend to connect the ports of the NewString and Concat components. We use HPC++ as the middleware to establish a communication channel between these two components. Towards this goal, stubs and skeletons need to be generated. The concept of stubs and skeletons is endemic to the distributed computing community. It is a design mechanism by which the low level details are hidden from an end user. The end user is presented with a single interface for local and remote component instantiation.

However, please note that the stub compiler is *not* included with the CCAT release. We are still working on it. As of now, these stubs and skeletons need to be generated by hand. We are waiting for Livermore's CASC SIDL to be released so that we can replace our IDL with it. Please continue to monitor our CCAT web page to learn about latest developments on this front.
The code to be generated by the stub compiler looks as follows:

// Do not modify. This file has been automatically
// generated from the IDL file MyString.idl
// File: MyString_idl.h

#ifndef _MY_STRING_IDL_H__
#define _MY_STRING_IDL_H__

#include  "MyString.h"  
#include "../InterfaceType.h"

class MyString_idl : public InterfaceType {
public:
  virtual int sendMyString(MyString *myString) = 0;
};

#endif // _MY_STRING_IDL_H__

The complexity of the low level details are hidden in the following files that are generated by the stub compiler:
  1. ProvidesMyString.h
  2. ProvidesMyStringSkel.h
  3. ProvidesMyStringSkel.C
  4. UsesMyString.h
  5. UsesMyStringSkel.h
  6. UsesMyStringSkel.C
  7. PORTS_REGISTRATION_ID.h

Port Compatibility

Two ports are said to be compatible if they are generated from the same idl. The IDLs used by the CCAT are retrieved from a central database of IDLs and as such are guaranteed to be unique across the CCAT users-community.

Parameter Ports

Ports are the traditional way of channeling data in the world of component based computing. The CCAT design however believes in providing the user additional tools to steer the computation. Parameter Ports are designed as provides ports for components that need run time settings for their computations. The CCAT composition gui component is equipped to detect that a component needs parameter ports by parsing the XML specification for the component. This composition engine generates a parameter gui for so that a user can specify some parameters to model the computation according to her needs. In our contrived NewString-Concat example, lets assume that a user wants the Concat component to take in two parameters, a long and a string . The long will specify the number of times the concatenation needs to be done and the string will be used to concatenate with the string generated by the NewString component.
Since this parameter setting needs to be done via a port, it needs to be specified in an IDL and the stub compiler has to be used to generate the necessary code to glue it with the framework.
The IDL for the parameter port can be as follows:

// File: Concat.idl
// This is a specification in IDL
// for the port of type MyString

interface ConcatParms : Port {
   int replyValue sendConcatParms(ConcatParms concatParms);
   int start();
   int stop();
   int kill();
};

// End of file Concat.idl

The extra methods start , stop and kill seem to imposing centralized control over the execution flow in CCAT. This notion is partially true. CCAT doesn't impose this design but provides it as an additional tool for use in some special cases. When an end user decides to steer the computation in a different direction by providing some parameters via the parameter port , CCAT sends a stop signal to the component. The component is expected (not bound) to stop after its current iteration on receiving this signal. CCAT then sends the new parameter setting via the sendConcatParms remote method call. Once the data structures of the component have been modified to the user's satisfaction, a start signal is sent to the component to resume its computation. The kill signal is used by the user when she wants to free the resources held by the component.
  1. ConcatParms_idl.h
  2. ConcatParms.h
  3. ProvidesConcatParmsSkel.h
  4. ProvidesConcatParmsSkel.C
  5. UsesConcatParms.h
  6. UsesConcatParmsSkel.h
  7. UsesConcatParmsSkel.C
  8. PORTS_REGISTRATION_ID.h

Component Initialization

Component Initialization is the process of initializing some data structures so that a component can co-exist in peace with the other components in the CCAT federation. Components are created using the singleton model from the creational pattern school of design. Each component is provided with a home, a concept inspired from EJB. We even provide each component with a thin HPC++ wrapper so that it can be instantiated via gram . Code in the following files explains the process of initialization for the Concat Component. Since these files are expected to be generated by the stub compiler, the code for the NewString component can be developed similarly.
  1. ConcatComponentHome.h
  2. ConcatComponentHome.C
  3. ConcatServer.C

Component Interface Implementatation

Since the stubs and skeletons handle all the communication and framework details, the component developers are expected to abide by a strict inheritance pattern in their code so as to be able to receive method invocations from remote processes. The following files provide the template that component developers must follow in order to be CCAT compliant. Please mark the comments (yes ! in a stunning display of software engineering, I have included some documentation here) or else you will greeted by core dumps at the time of execution.
  1. ConcatComponent.h
  2. ConcatComponent.C

Provides Port Implementatation

The end user is supposed to provide an implementation of the provides port that (s)he registered in the setServices() method while implementing the component interface implementation. The inheritance structure *has* to conform to what the CCAT stubs and skeletons expect as illustrated in the code presented in the following files:
  1. MyString_impl.h
  2. MyString_impl.C
  3. ConcatParms_impl.h
  4. ConcatParms_impl.C

Uses Port Interface Implementatation

The CCA design mandates that the framework manufacture the uses port for all the IDL specifications presented by the user. The user is provided with a handle to the uses port implementation whenever he asks for it.
// Typically the NewSystem component upon generation of a
// new string will propagate it to the Concat component
// via its uses port for MyString_idl

// UsesMyString: type of the output port
// m_core: pointer to the services object
// "outputMyString": name given to the port in registerUsesPort() call

 UsesMyString *up = dynamic_cast(m_core->getPort("outputMyString"));
 up->sendMyString(pointerToNewString);
 m_core->releasePort("outputMyString");

Flow of Control

The CCA specification does not specify the flow of control of the system of connected components. CCAT provides the user with an option of starting, stopping and killing components via the parameter ports. This, we belive, will be the most common way to kick off any execution cycle.

XML specification

The components are described using XML technology. We provide the XML description for NewString and Concat as examples. These XMLs conform to this DTD .
  1. XML for Concat
  2. XML for NewString

Incorporating into CCAT

All these new files that we have talked about so far need to be placed into specific places in the CCAT hierarchy. (More details on this soon).

Installing components

(More details on this soon)
mgovinda@cs.indiana.edu
Last modified: Wed Jan 26 20:08:21 EST 2000