OpenCCM - Home Page

Table of contents

  1. Development process overview
  2. Writing interfaces
  3. Implementing components
  4. Writing workspace and project files
  5. Compiling the application
  6. Deploying the application

Development process overview

Development

  • The user has to design the interfaces of components in IDL3 language (IDL3 files) and IDL2 interfaces used by the components.
  • Then he shall define the implementation of components methods of provided interfaces (facet) and push methods for events sinks (for example classes inherited from executors object).
  • The user has to create an MPC file for the project. It contains definitions of all the components files implied in the application: the user declares files (implementation of component provided interfaces, IDL3 files) and the generated files (microccm_*).

Compilation

The following commands generate all "Makefile" files and compile them by typing:

          $generateMakefiles.sh  name_of_workspace.mwc
	  $make
	

Resulting files and components utilisation

  • This aims to generate IDL2 mapping of IDL3 components, and two C++ files: one defining the "monolitihic" executor and the other one the CORBA implementation following Lightweight component model features like ports, etc. Besides, the latter generates contains the needed features to define generic interceptors for container services.
  • All the IDL2 files are then compiled by the ORB IDL compiler. This generates all stubs and skeleton code of interfaces.
  • In turn, all the generated c++ files (executor, CORBA run-time, stubs and skeletons) and their corresponding implementation files are compiled with the chosen C++ compiler.
  • The application can be used at this step. The user can deploy himself all the components on different hosts, thanks to HomeFinder and Component_Loader tools. But in case of using many components and complicated configurations for each one it is better to use a deployment tool. The user has to write XML files for configuration and packaging. Then, he has to launch the deployment tool which installs (deployment on different hosts), makes assembly, and configures the components application.

Writing interfaces

This example involves two components:

  • component1: This component contains different types of ports: it provides a facet (I1 interface) and contains a receptacle accepting I2 interface. This component contains two event sources, publishing two kinds of event: MyEvent1 and MyEvent2. Besides, it contains an event sink to consume MyEvent1 event.
  • component2: This component contains a facet (it can provide I2 interface) and a receptacle (It can use I3 interface). Therefore, it contains two event sinks consuming MyEvent1 and MyEvent2 events.

Here is the component1.idl3 file :

	   #include <component1_intf.idl>
           component component1
           {
             provides	I1		my_interface_1;
             uses	I2		my_interface_2;

             publishes	MyEvent1	MyEvent1_source1;
             publishes	MyEvent2	MyEvent2_source1;
             consumes	MyEvent1	comp1_Myevent1_sink1;
           };

           home component1_home manages component1 { };

	

Here is the component1_intf.idl defining all provided interfaces (facet) and event type:


           interface I1 {
           string do_something();
           void send_event();
           };

           interface I2 {
           void do_something();
           };

           eventtype MyEvent1 {
           public string event_name1;
           };

           eventtype MyEvent2 {
           public string event_name2;
           };
	

We can notice the facet, the receptacle and the two event source and the event sink. Besides, we can see that this file includes the IDL2 interface needed I2. Moreover, while making the mapping from this IDL3 file to the corresponding IDL2 file, the declaration of the component will need the declaration of MyEvent1 and MyEvent2, so we must declare this two kinds of event thanks to the keyword eventtype.

Here is the component2.idl3 file:

           interface I2 {
           void do_something();
            };

           interface I3 {
           string say_something();
           };

           eventtype MyEvent1 {
           public string event_name1;
           };

           eventtype MyEvent2 {
           public string event_name2;
           };

           component component2  {
           provides	 I2 		my_facet_I2;
           uses		 I3		my_recept_I3;
           consumes	 MyEvent1	MyEvent1_sink_1;
           consumes	 MyEvent1 	MyEvent1_sink_2;
           };

           home component2_home manages component2 { };
	

We can see the facet , the receptacle and the two events sink.

Implementing components

Implementing "Component2" (consumer) component

The class CCM_component2_impl inherits from CCM_component2, which contains all the methods that need to be implemented by the user, it corresponds to methods of interfaces defining in the IDL3 file.

Besides it inherits from all the interfaces corresponding to facets, in the example, CCM_I2. And finally, it inherits from CCM_component2_SessionComponent_impl, which permits to access to the container, and receptacles via the context. So the user has to implement all the facets. For instance, there is a facet "I2" contains a method do_something2, so it is implemented as we can see in the file "component2_impl.cpp". Besides, he has to implement the method push_MyEvent1_sink, in order to defined the behaviour while an event, of type "MyEvent1", has been received on the sink "MyEvent1_sink". And the same for the method push_MyEvent2_sink.

Implementing "Component1" (publisher) component

The class component1 inherits from executor class CCM_component1, which contains the virtual method to get the provided interfaces (facets) (i.e. get_my_interface_1), and the configuration_complete method.

So the user has to implement the facets, as we can see in the file "component1_impl.cpp", i.e. the class CCM_I1, which delegates the interface defined in the IDL3 file. The class has twomethods: do_something() and send_event().

As for component2, it inherits from CCM_component1_SessionComponent_impl, which permits to access to the container, and receptacles via the context.

The method send_event() use the "push_MyEvent1_source1 (MyEvent1)" method, via the context, to send events (MyEvent1) to component consumers (sink) of the corresponding type.

Writing workspace and project files

MWC file

This file consists in declaring MPC projects files to call. In our example "events.mwc" file contains the following lines:

	workspace {
	events.mpc
	}
	

MPC files for "client".

Here is the mpc project to create the "client.exe" executable file.

This project aims to create the client executable called "client.exe", thanks to the code "client.cpp".

It must inherit from another project "mccm_comp_client". It contains all the common definitions (project variables, includes, libs, etc.) in order to create the right Makefile templates for a client that uses TAO ORB.

Some specific project elements have to be added, in order to compile correctly, for example, the name of the IDL3 files, name of interfaces used in the client code.

        project (test_client):  mccm_comp_client {

	exename = client.exe

	IDL3toIDL2intf_Files {
		commandflags += I1
                explicit_outputs = microccm_I1.idl 
	 component1.idl3
	}
	
	IDL3toIDL2intf_Files {
		commandflags += I2
	explicit_outputs = microccm_I2.idl 
		component2.idl3
	}
	
	IDL_Files {
		microccm_I1.idl
		microccm_I2.idl
	}
	
	Source_Files {
		client.cpp
	}
}
	

Firstly, the user has to choose the right generator. All the generator executables and the corresponding shared libraries are ready (i.e. respectively in the $microCCM_DIR/bin and $microCCM_DIR/lib directories). The purpose of this mpc file, is to generate the makefile(s) with the right compiler options (librairies, includes etc.) as well as the right IDL3 compilers (idl3_to_idl2.exe, idl3_to_corba.exe and idl3_to_cpp_executor.exe). These options are set in the file codegen_config.txt. For the moment, only two possibilities are provided:

  • Either, the user generates I1 and I2 (stubs and skeleton) codes for TAO ORB (USED_GENERATOR=tao_generator in codegen_config.txt), thanks to the OpenCCM Interface Repository (USED_IFR=openccm_ifr has to be set in the codegen_config.txt).
  • Or, he can generate the same code (for TAO), but this way, with TAO Interface Repository, this is the default configuration (USED_IFR=tao_ifr has to be set in the codegen_config.txt).

MPC files for "components".

In "events.mpc" file, we can find two projects:

Here is the project for the component1, "events_commponent1" in "events.mpc" file:

	
	project (events_component1): mccm_comp_project {

	newdirs += generated	
	includes += . ./generated
	
	sharedname = component1

	IDL3IDL2_Files {
	commandflags = component1 component1_home
	explicit_outputs = microccm_component1.idl
	component1.idl3
	} 


	IDL3CPPEXECUTORS_Files {
	commandflags = component1 component1_home
	explicit_outputs = microccm_component1_executor.h microccm_component1_executor.cpp
	component1.idl3
	}
	

	IDL3CPPCORBA_Files {
	commandflags = component1 component1_home gen_desc_file.txt
  	explicit_outputs = microccm_component1_CORBA.h 	microccm_component1_CORBA.cpp
	component1.idl3
	} 	
	
	IDL_Files {
	microccm_component1.idl
	}
	
	Source_Files {
	component1_impl.cpp
	microccm_component1_executor.cpp
	microccm_component1_CORBA.cpp	
	}
	
	Header_Files {
	component1_impl.h
	microccm_component1_executor.h
	microccm_component1_CORBA.h
	}
} 
	

Here is the project for the component2, "events_commponent2":

	project (events_component2): mccm_comp_project {

	newdirs = generated
	includes += ./generated
	includes += .
	
	sharedname = component2

	IDL3IDL2_Files {
	commandflags = component2 component2_home
  	explicit_outputs = microccm_component2.idl
	component2.idl3
  	} 


	IDL3CPPEXECUTORS_Files {
	commandflags = component2 component2_home
  	explicit_outputs = microccm_component2_executor.h microccm_component2_executor.cpp
	component2.idl3
	}
	

	IDL3CPPCORBA_Files {
	commandflags = component2 component2_home gen_desc_file.txt
  	explicit_outputs = microccm_component2_CORBA.h microccm_component2_CORBA.cpp
	component2.idl3
	} 
		
	IDL_Files {
	microccm_component2.idl
	}
	
	Source_Files {
	component2_impl.cpp
	microccm_component2_executor.cpp
	microccm_component2_CORBA.cpp	
	}
	
	Header_Files {
	component2_impl.h
	microccm_component2_executor.h
	microccm_component2_CORBA.h
	}
}
	

Compiling the application

Generating Makefiles from MPC files

All the projects need a workspace file (.mwc) in order to generate a Makefile, which in turn call all Makefile.name_of_project, one per project, corresponding to the name_of_project declared in the .mpc files. In the directory $microCCM_DIR/bin, there is a script called "generateMakefiles.sh" which takes the mwc file as parameter and permits to launch the creation of all the project makefiles.

the user has to type on the shell command :

	$ generateMakefiles.sh events.mwc
	

Then four files are generated:

  • Makefile
  • Makefile.test_client
  • Makefile.events_component1
  • Makefile.events_component2

Compiling the project.

In order to compile the project the user has to type:

	$ make
	

Deploying the application

Introduction

In order to use components, and manage them, they have to be deployed, connected and started. In the CCM specification, the deployment is provided by deployment code or Deployment and Configuration specification. To deploy components, created by the microCCM framework, in the same process, a specific tool is used.

The main goal of this tool, is to allow the user to test all the components.

The process consists in first, loading all components thanks to HomeFinder and Component_Loader tools (registering component's Home via the HomeFinder).

Then, a "client" written by the user, is started. Like a deployment could do, it retrieves the Home, instantiates, configures components, connect them, and finally, execute pre-defined a scenario.

Found in the directory $microCCM_DIR/deployment/Component_Loader, this tool permits to deploy components in the same process. It aims to read a file, describing a list of components and services, and loads the corresponding one. All the components to deploy have to be declared in a file in the directory where Component_Loader.exe are started, "Comp_loader_file.txt" as shown below:

          Component_lib ../component1/libComp1.so      Comp1_home              create_home_exec
          Service_lib   ../Trace_service/libTrace.so   register_trace_service
          Normal_lib    libUtils.so
	

Run the TAOs Naming Service in a shell terminal

The user must run the TAO's Naming Service in order to bind and retrieve all the objects the user can type:

	$ startnameservice
 	

This command permits to start the naming_service on a localhost, or one can use the following command:

	   $TAO_ROOT/orbsvcs/Naming_Service/Naming_Service -ORBEndPoint iiop://host:port -o naming.ior -m 0
	

where "host" is the IP address or hostname of the host where the Naming Service is running, and "port" is the port number on which the naming service is launched.

Run the Event channel factory

If the components use Events sink or source, the channel factory must be started. The user can type the following command to start the factory on the localhost:

          $ startfactory
	

Or, he can use the following command:

	   $ $microCCM_DIR/services/events/factory -ORBInitRef NameService=corbaloc:iiop:host:port/NameService
	

where "host" is the IP address or hostname of the host where the Naming Service is running, and "port" is the port number on which the naming service is launched.

Run the HomeFinder

In order to retrieve components, the HomeFinder tool has to be started the user has to type:

           $ HomeFinder.exe
	

Run the Component_Loader

In order to load all components shared library, the user has to type:

           $ Component_Loader.exe Comp_loader_file.txt  -ORBInitRef NameService=corbaloc:iiop:host:port/NameService 
	

Run binary files aims to instantiate the « client.exe »

Once the factory IOR has been, displayed, the user can start the example:

           $./client.exe -ORBInitRef NameService=corbaloc:iiop:host:port/NameService
	

This operation launches the client which "starts" components.

Copyright Thales 2003-2005.

Copyright © 1999-2005, ObjectWeb Consortium | contact | webmaster | Last modified at 2005-07-07 02:04 PM