Trentino - User Manual

Kwemou Emeric

Sokolov Konstantin

Erkmen Muge

Höller Oliver

Smirnov Alexander

Tatli Ipek

Trentino 0.2

Copyright (C) Siemens AG, 2010-2012 All Rights Reserved

Copies of this document may be made for your own use and for distribution to others, provided that you do not charge any fee for such copies and further provided that each copy contains this Copyright Notice, whether distributed in print or electronically.


1. Trentino Introduction
1.1. Enable extensible architectures
1.2. Lightweight Runtime
1.3. Target users
1.4. Contribution development process
2. What's New in Trentino 0.2
3. Trentino Console HowTo
3.1. Overview
3.2. Help command
3.3. Install command
3.4. Remove command
3.5. Info command
3.5.1. Retrieving information about contributions
3.5.2. Retrieving information about available components
3.5.3. Retrieving information about single components
3.5.4. Retrieving information about single services and references
3.5.5. Retrieving information about single properties
4. Trengen: Trentino validation and code generation tool
4.1. Overview
4.2. Contribution validation
4.2.1. Usage
4.2.2. Syntax validation
4.2.3. Semantic validation
4.2.4. Assumptions and limitations
5. Trentino Binding Tutorial
5.1. Trentino default (SCA) Binding
5.1.1. Overview
5.1.2. Creating sample server and client applications, their interfaces, deploying and running
5.1.2.1. Create the Helloworld server application
5.1.2.2. Create the HelloWorld client application
5.1.2.3. Deploy and run
5.1.3. Binding-related generated files
5.1.4. Binding.sca from development point of view
5.2. Trentino IPC Binding
5.2.1. Overview
5.3. Extending bindings in Trentino (using TIDL / IDL)
6. Trentino Interface description language (TIDL) reference
6.1. Overview
6.2. Why do we need TIDL?
6.3. Example interface
6.4. TIDL types
6.4.1. Simple types
6.4.2. Complex types
6.4.3. Exceptions
6.5. Interface
6.5.1. Import section
6.5.2. Interface Methods
6.5.3. Methods arguments
6.5.3.1. @In Annotation
6.5.3.2. @Out annotation
6.5.3.3. @InOut annotation
6.6. C++ code generation
6.6.1. Example generated C++ code
6.6.2. Providing default values at model level
7. Trentino Service Discovery
7.1. Reference and Service Wiring with Service Discovery
7.2. Enabling and Configuring Service Discovery
7.2.1. Service Discovery Configuration in Runtime.conf
7.2.2. OpenSLP and its configuration
7.2.2.1. OpenSLP configuration file
8. configuration before contribution deployment
8.1. Editing sca-contribution.xml before deployment
8.2. Changing dll-directory at install time
Appendix A. Validated SCA constraints
Appendix B. OpenSLP error codes
Glossary

Chapter 1. Trentino Introduction

TRENTINO is an open source platform that enables and simplifies the task of developing and managing SOA based embedded systems by providing a comprehensive infrastructure based on Service Component Architecture (SCA) standard. Trentino severely reduces complexity and thus has positive implications on cost during the entire application lifecycle of your product.

1.1. Enable extensible architectures

Trentino has been designed from the ground up to eliminate complexity at both architecture and API levels. It provides the following keys features to the embedded developers

  • A standard based component model

  • Plugable communication protocols (SCA Bindings)

  • A Management and monitoring component for Trentino applications

  • Distributed Service discovery

  • Trentino is non invasive: Minimal API, use of dependency injection. It therefore facilitate the migration of existing C++ code base to a Trentino Runtime.

1.2. Lightweight Runtime

The main goal of Trentino is to be as lightweight as possible. An empty Trentino runtime has a memory footprint lower than 500 KB.

1.3. Target users

Trentino has been designed as generic as possible to be integrated in allmost all kind of embedded applications. The minimal requirements for Trentino is that the embedded device should host an Operating System. The Source code can be compiled for Visual Studio and GCC platforms (including QNX).

Trentino is licensed under Apache License, Version 2.0. Full commercial support is available from Siemens Corporate Technology. Tooling for Trentino applications are provided.

1.4. Contribution development process

The development of an SCA contribution (see glossary for definitions) is done in four steps:

  • Develop and test SCA services

  • Assemble SCA contribution

  • Prepare for deployment using Trengen

  • Deploy on a Trentino runtime

Chapter 2. What's New in Trentino 0.2

Trentino 0.2 has six major themes:

  • Trengen was completely rewritten is java

  • Support a subset of the Service Component Architecture specification: Contribution, composites, components, manual wiring.

  • Support of SCA Properties (all xml simple types) Property query from the Trentino console

  • Support for remote communication by: Combining google protocol buffer and binary SOAP as communication protocol Using ZeroMq as intelligent and reliable Transport layer

  • Support for SCA C++ API: Domain and ComponentContext

  • Management console

  • Components lifecycle methods

Chapter 3. Trentino Console HowTo

3.1. Overview

Trentino’s console is a separate executable tool that lets the user interact with the Trentino Runtime. The Runtime itself is not aware of the existence of the console and offers its functionality over a well- defined interface. From the user’s point of view the runtime can be controlled by a set of commands offered by the console. On startup the console prints an intro message and changes to the command prompt:

 
----------------------------------------------------------------------
** TrentinoConsole, TRENTINO's deployment console
** Copyright (C) Siemens AG, 2012. All rights reserved.
** TRENTINO is released under the LGPL License
----------------------------------------------------------------------
Trentino> 

3.2. Help command

The help command can be used to retrieve a list of the supported commands along with a short description:


Trentino> help
Commands available in this console:
    boot       - boot the Trentino runtime into the current process
    shutdown   - unload the Trentino runtime from the current process
    install    - install, deploy and run a contribution
    remove     - remove an installed, deployed or running contribution
    info       - retrieve information about installed entities from the runtime
    quit, exit - quit from this console

Try commands above with '-h' option for more information

3.3. Install command

Every command except for quit and exit can be called with the –h option to retrieve a more detailed usage description. The first step for using the Trentino runtime consists in booting it with the help of the boot command. Once the runtime is booted the install, remove and info commands can be used to interact with it. Using them before booting will issue the “management interface not available” error. The runtime can be unloaded from the current process by using the shutdown command. A graceful shutdown is also performed by using the quit or exit commands (there is no difference between quit and exit) that additionally terminate also the console itself. The install command is responsible for installing, deploying and running a contribution. The installation steps solely loads a contribution into memory without to perform SCA error and consistency checking. Errors issued during the installation process may concern only the non-existence of expected contribution dynamic libraries and configuration files. Wiring and consistency checking is performed in the deployment step. Finally, before the contribution is put in the Running state, all @eagerInit=”true” component implementations are instantiated. Currently all the three steps are executed automatically. The install command expects two arguments: a path to the contribution folder and a contribution base URI under which the contribution is to be installed into the domain. Example:


Trentino> install  C:\conributions\someContribution some.contrib.uri

3.4.  Remove command

A contribution can be removed using the remove command. It reverts all the steps performed by the install command and completely removes the contribution from memory. remove expects a contribution base URI as argument.


Trentino> remove some.contrib.uri

3.5. Info command

The info command is used to retrieve different information about SCA entities available in the runtime.


Trentino> info –h
Retrieve the information about installed entities from the runtime.
Usage:
    info [-h] [-s] [-q(b|c|rsp)] URI
    -h    show this message
    -s    show entities status
    -q    perform a request by using the following specifiers:
      b   retrieve contributions
      c   retrieve components
      r   retrieve references
      s   retrieve services
URI may be one of the following type: contribution base URI, component,
reference, service, property. To retrieve a list of all the domain-level
components leave the URI empty. To retrieve as list of installed contributions
leave the URI empty.


3.5.1. Retrieving information about contributions

info –qb will retrieve a list of all contribution available in the runtime


Trentino> info –qb
[contribution]: some.contrib.uri
[contribution]: other/uri

info –s –qb additionally shows the contribution states


Trentino> info –s –qb
[contribution]: some.contrib.uri (Running)
[contribution]: other/uri (Running)

It’s also possible to pass a contribution base uri to the info command in order to retrieve information about a specific contribution. Since it’s currently not possible to retrieve other information than the contribution’s state info –qb some.contrib.uri is the same as –qb -s some.contrib.uri


 Trentino> info -qb some.contrib.uri
[contribution]: some.contrib.uri (Running)
 

3.5.2. Retrieving information about available components

info –qc will retrieve a list of all the domain-level components (i.e. components not contained in a composite used as implementation). Components are referenced by their structural URI.


Trentino> info –qc
[component]: BuilderComponent
[component]: LoggerComponent
[component]: GUIComponent

info –qc some.contrib.uri will retrieve a list of all the components contained in the contribution with the given base URI.


Trentino> info -qc some.contrib.uri
[component]: BuilderComponent/BuilderImplComponent
[component]: BuilderComponent/LinkerComponent
[component]: BuilderComponent/CompilerComponent
[component]: LoggerComponent/SmartLoggerComponent/SmartLogger
[component]: LoggerComponent/LoggerImpl
[component]: LoggerComponent/SmartLoggerComponent
[component]: BuilderComponent
[component]: LoggerComponent
[component]: GUIComponent

Notice the structural URI style: LoggerComponent/SmartLoggerComponent/SmartLogger for example means that SmartLogger is contained in a composite used as SmartLoggerComponent’s implementation while SmartLoggerComponent itself is contained in a composite used as LoggerComponent’s implementation. The -s option can be specified also for components to retrieve their states: info –s –qc some.contrib.uri

3.5.3. Retrieving information about single components

In order to retrieve information about a specific component, the component’s URI must be passed to the info command. The simplest case is as follows: info GUIComponent will do nothing except for showing the passed component URI as output. This can be used to check for the existence of a component:


Trentino> info GUIComponent
[component]: GUIComponent
Trentino> info nonExistent
ERROR - Component with URI 'nonExistent' not found
Trentino>

info –s GUIComponent will additionaly show the component’s state


Trentino> info -s GUIComponent
[component]: GUIComponent (Resolved)

The –q option can also be used with any combination of the s, r and qqualifiers. For example –qs, -qr, -qp, -qrs, -qrsp etc. Where s retrieves information about services, r about references and p about properties.


Trentino> info -qsr LoggerComponent/LoggerImpl
[component]: LoggerComponent/LoggerImpl
    [references]:
        FileLogger
        ConsoleLogger
    [services]:
        Log

Additionally using the the –s options will retrieve also the state of the component as well as the states and wiring information of the services and references.


Trentino> info -s -qrs BuilderComponent/CompilerComponent
[component]: BuilderComponent/CompilerComponent (Resolved)
    [references]:
        Log (Resolved) -> LoggerComponent#service(Log) LoggerComponent#service(Log)
    [services]:
        ExecuteCompiler (Available)

The output tells us that CompilerComponent’s reference with the name “Log” is wired twice to the “Log” service implemented by the LoggerComponent. Furthermore CompilerComponent offers an “ExecuteCompiler” service that is in Available state.


Trentino> info -qp Person1
[component]: Person1
    [properties]:
        Name ( 'John Doe' )
        Age ( '23' )
        FavouriteNumbers ( '3' '9' '23' )

The p qualifier shows all the available properties and their values.

3.5.4. Retrieving information about single services and references

In order to retrieve information about a specific service or reference, its structural URIs must be passed as argument. Example:


Trentino> info -s LoggerComponent/LoggerImpl#reference(FileLogger)
[references]:
    FileLogger (Resolved) -> LoggerComponent/SmartLoggerComponent#service(FileLogger)
Trentino> info  -s BuilderComponent/LinkerComponent#service(ExecuteLinker)
[services]:
    ExecuteLinker (Available)

3.5.5. Retrieving information about single properties

In order to retrieve information about a specific property, its structural URIs must be passed as argument. Example:


Trentino> info Person1#property(Name)
[properties]:
    Name ( 'John Doe' )

Chapter 4. Trengen: Trentino validation and code generation tool

4.1. Overview

Trengen is the validation and generation tool of Trentino runtime. It validates users contribution and generates many artifacts necessary extra artifacts that are used by the runtime to access, execute and manage the deployed contribution. Generated artifacts include:

  • Reflection code: C++ source code necessary by the runtime in other to perform dependency injection.

  • Serialization and Deserialization code: needed by the runtime or by a Trentino client to handle remote procedural calls.

  • Proxies and skeletons classes for the defined services

4.2. Contribution validation

4.2.1. Usage

Trengen validates the contribution against Service Component Architecture v1.1 (SCAAM v1.1) and SCA client and implementation Model for C++ Specification V1.1.



USAGE 1:
trengen -cont <contribution_directory> -outdir <output_directory*> -lib <libname*>
        -libdirs <directory*> -includedirs <directory*> -d* -rtdir <runtime_directory*>
        -install_dir <contribution_installation_directory*> -v*

OPTIONS:
-cont <contribution_directory>|<zip_file_of_contribution_directory_tree>: specifies
        the root directory of SCA contribution, can be a zip file or a path.
-outdir <output_directory*>: If provided it specifies the output directory for the
        Trengen generated code. Default is <input_directory>Gen.
-lib <libname*>: Library names (not path) of the service/component implementations.
        Names are separated by ';' or ':'. Default is the contribution name.
-libdirs <directory*>: path separator separated list of directories, where libraries
        containing the service/component implementations are located. Default is <root>
        and <root>/lib.
-includedirs <directory*>: path separator separated list of directories, service and
        component header files are located. Default are <root>, <root>/services and
        <root>/include.
-d*: Optional. If provided, Trengen runs in debug mode. Default is -r.
-v*: Optional. If provided, Trengen shows info logs.
-rtdir <runtime_directory*>: specify the location of the Trentino Runtime. Optional
        since Trengen tries to resolve the runtime from itself.
-install_dir <contribution_installation_directory*>: Optional. Trengen generates a
        Cmake file for the generated code. It requires the location where binaries
        will be installed as result of a Cmake install. Default value is the 'META-INF'
        of the <contribution_directory>.

USAGE 2:
trengen -gencppitf <path to properties file>.properties> -inc <header file name*> -outdir <path to output dir
*>

OPTIONS:
-gencppitf <path to properties file>.tidl.properties: The tidl configuration file containing
        the information about the interface to be generated.The tidl file is a java resource
        file.It should contain an entry indicating the location of the interface to be used.
        If the path is a directory, then all *.tidl.properties files in the given directory will be processed

-inc    <header file name*> name of an optional header file to be included in the generated C++ header file.
-outdir <path to output dir*>: The path to the output directory this parameter is
        optional. The default value is the current directory.


I:\Trentino\trentino\DEV\cpp_build>


		Trengen outputs the generated code along with a cmake file under the [ContributionName]Gen folder at the same level with the contribution folder. The user should compile the generated code according to the provided CMake. As the result of the compilation of generated code the “sca-contribution.dll”, “sca-contribution.lib”, “sca-contribution.conf “ files are placed under the META-INF folder of the contribution. (For detailed sequence please see section :Compiling and Installing A Sample Contribution)


 

The validation includes a syntax and a semantic validation.

4.2.2. Syntax validation

The Syntax validation validates the contribution and its artifacts (componentType files, composites, contribution documents, ...) against specified xsd schemas provided by the SCA specification.

  • *.componentType files are validated against sca-interface-cpp-1.1-cd06.xsd

  • *.composite files are validated against sca-implementation-cpp-1.1-cd06.xsd, sca-implementation-composite-1.1-cd06.xsd, sca-interface-cpp-1.1-cd06.xsd, sca-interface-wsdl-1.1-cd06.xsd and sca-binding-sca-1.1-cd06.xsd.

  • sca-contribution.xml is validated against sca-contribution-cpp-1.1-cd06.xsd.

  • sca-definitions.xml is validated against sca-definitions-1.1-cd06.xsd.

To get the list of all syntax constraints that are validated by Trengen, please see Appendix A.

4.2.3. Semantic validation

Semantic validation takes place after and if syntax validation was successful. It includes validation of the relationship between artifacts, the consistency of the whole contribution as defined by the SCA Specification

4.2.4. Assumptions and limitations

  • Trengen have to parse you provided source code to check that required dependency injection points (setter accessors) are implemented. Trentino only parses header files and no *.cpp files. It therefore assumes that at least the definition of your setters are in the header files to be parsed.

  • TrenGen validates/parses/uses only 1 contribution (given as a zip file or a directory).

  • TrenGen does not support domain-specific issues (like import, export, domain-level composite).

  • TrenGen does not support nor validate sca policies and intents, since they are currently not supported by Trentino.

  • We assume that the composite files will be unique within the whole tree of the given sca validation directory (param of trengen)

  • While finding the matching .componenttype file of a component, if the component/implementation/@componentType is not defined, we search the .componenttype file named according to the component/implementation/@class within the whole contribution tree.

  • We have assumed the specification regarding the service interfaces(i.e ASM60005) are also valid for the callback interfaces.

  • Namespaces defined by extra xsds and annotations are not supported for now. For extensive property support it might be required.

Chapter 5. Trentino Binding Tutorial

Service Component Architecture (SCA) supports many communication protocols. In SCA terms, these are called bindings. Bindings encapsulate the complexities of communication protocols and enable components to be implemented and wired together without a direct dependency on the communication protocols used.

What does this mean in reality? It means that an SCA developer can implement a component without polluting the business code with details of how the communication between components will be handled. This separation of concerns has the added advantage of making the communication protocol a pluggable entity that can be changed at any time based on how and where the component is deployed.

Bindings are used by services and references. References use bindings to describe the access mechanism used to call a service (which can be a service provided by another SCA composite). Services use bindings to describe the access mechanism that clients (which can be a client from another SCA composite) have to use to call the service.

SCA supports the use of multiple different types of bindings. Trentino supports SCA binding via TCP/IP. Trentino will also support interprocess communication binding via shared memory, REST binding, bacnet binding and profinet binding.

SCA provides an extensibility mechanism by which an SCA runtime can add support for additional binding types. A binding is defined by a binding element which is a child element of a service or of a reference element in a composite.

The following snippet shows the binding element pseudo-schema.



<?xml version="1.0" encoding="ASCII"?>
<!-- Bindings schema snippet -->
<composite ... >
...
  <service ... >
   <interface … />
    <binding uri="xs:anyURI"? name="xs:NCName"? requires="list of xs:QName"?policySets="listof xs:QName"?>
     <wireFormat/>
     <operationSelector/>
     <requires/>
     <policySetAttachment/>
    </binding>
    <callback>
     <binding uri="xs:anyURI"? name="xs:NCName"? requires="list of xs:QName"? policySets="list of xs:QName"?>
      <wireFormat/>
      <operationSelector/>
      <requires/>
      <policySetAttachment/>
     </binding>
    </callback>
  </service>
  <reference ... >
   <interface … />
    <binding uri="xs:anyURI"? name="xs:NCName"? requires="list of xs:QName"?policySets="listof xs:QName"?>
     <wireFormat/>
     <operationSelector/>
     <requires/>
     <policySetAttachment/>
    </binding>
    <callback>
     <binding uri="xs:anyURI"? name="xs:NCName"? requires="list of xs:QName"? policySets="list of xs:QName"?>
      <wireFormat/>
      <operationSelector/>
      <requires/>
      <policySetAttachment/>
     </binding>
    </callback>
  </reference>
</composite>


 

5.1. Trentino default (SCA) Binding

5.1.1. Overview

SCA binding for Trentino is done via TCP/IP. Following snippet shows the SCA binding element pseudo-schema.



<binding.sca uri="xs:anyURI"? name="xs:NCName"? requires="list of xs:QName"? policySets="list of xs:QName"?>
 <wireFormat/>?
 <operationSelector/>?
 <requires/>*
 <policySetAttachment/>*
</binding.sca>


 

The following SCDL is an example for the usage of binding.sca in Trentino.



<?xml version="1.0" encoding="utf-8"?>
<composite name="BasicCalculatorRemoteClientComposite" xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912" targetNamespace="BasicCalculatorNamespace">
  <component name="BasicCalculatorRemoteClientImpl">
    <implementation.cpp
        class="Trentino::Example::BasicCalculatorRemoteClient::BasicCalculatorRemoteClientImpl"
		header="TrentinoExampleBasicCalculatorRemoteClientBasicCalculatorImpl.h"
        scope="composite" eagerInit="true"
		library="BasicCalculatorRemoteClient" >
		 <function name="onInit" init="true" />
		</implementation.cpp>
     <reference name="BasicCalculatorRef" >
	 	<binding.sca uri="tcp://localhost:5342/BasicCalculatorImpl/BasicCalculator"/>
    </reference>
  </component>
</composite>


 

Each binding.sca (in Trentino) must have a "uri" attribute. The convention for the attribute is represented below:



tcp://localhost:5342/BasicCalculatorImpl/BasicCalculator


 

"Uri" attribute of binding.sca must begin with "tcp://" which is followed by a valid host and a valid port. Host and port checks are done by Trengen. End-user is informed when there are some errors during validation before deployment.

5.1.2. Creating sample server and client applications, their interfaces, deploying and running

In the next 10 minutes, we want to create a Hello World remote application and deploy it on two Trentino runtimes. The first runtime is a server and the second a client. On the Server, a contribution implementing the Helloworld Service is deployed. On the client, the contribution is having a reference using the service provided by server. The overall deployment diagram of our system is described in the following picture.

Assembly diagram of Helloworld remote

Assembly diagram of Helloworld remote

5.1.2.1. Create the Helloworld server application

Binding.sca is the default binding for all remotable services. If there are not any bindings specified for a remotable service, we can say that it uses binding.sca. If there are not any binding.sca specified, which port will be used by Trentino runtime? The Trentino runtime hosting the server application has a Binding.conf file. The contents of the Binding.conf is below:



binding.sca.port=5342
binding.sca.dll=TrentinoBindingSCA
binding.sca.thread.number=1
binding.sca.client.timeout=1500 #in miliseconds


The port in the Binding.conf is used if there are not any bindings in the remotable service. It is the port number that ZMQServer listens for a request and opens it for sending the response. End-user may edit the values of the parameters in the Binding configuration file.

5.1.2.1.1. Download all necessary files and setup development environment

Download and install the Trentino runtime as described in the Trentino Getting Started guide. It includes all the necessary binaries for developing a remote application. Now create a folder called HelloWorldRemote_Source. At the end of this section, we will end up with the following file structure:

Server folder structure

Server folder structure

Since the application developed in this tutorial is platform independent, we will use Cmake as cross platform build tool. And therefore we need to define a CMakeList.txt file describing our project. Create a file named CMakeList.txt and paste the following code into that file:



cmake_minimum_required(VERSION 2.6)
project(HelloWorldRemote)

set(PNAME HelloWorldRemote)
##############################################################################
# 									MACROS									 #
##############################################################################

#----------------------------------
# MY_LINK_THIRD_PARTY_LIBRARIES 
#----------------------------------
#The libs to be linked to are expected to be passed as additional arguments after 'target'.
#This arguments have to be uncomplete variable names representing the libs
#The macro will append '_DEBUG' respectively '_RELEASE' to the passed arguments
#in order to produce real variable names that are expected to contain the real lib names.
#EXAMPLE: 
#The call MY_LINK_THIRD_PARTY_LIBRARIES(main Boost_FILESYSTEM_LIBRARY) expects the variables
#'Boost_FILESYSTEM_LIBRARY_DEBUG' (if build type is debug) respectively 
#'Boost_FILESYSTEM_LIBRARY_RELEASE' (if build type is release) to be defined
#----------------------------
macro(MY_CREATE_VALIDATE_GENERATE_INSTALL_TARGET installDir)
if (WIN32)
	set(GEN_INSTALL_COMMAND msbuild INSTALL.vcxproj)
else()
	set(GEN_INSTALL_COMMAND make install)
endif()
add_custom_target([Trengen_Validate_Generate_Install] 
COMMAND Trengen	-cont ${installDir}
#create a build folder for the generated code
COMMAND ${CMAKE_COMMAND} -E make_directory ${installDir}Gen_Build
#build the project using cmake
COMMAND ${CMAKE_COMMAND} -E chdir ${installDir}Gen_Build cmake ../${installDir}Gen
#now install the application: on windows, call msbuild on linux call make
COMMAND ${CMAKE_COMMAND} -E chdir ${installDir}Gen_Build ${GEN_INSTALL_COMMAND}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/../
VERBATIM
)	
endmacro(MY_CREATE_VALIDATE_GENERATE_INSTALL_TARGET)



set (TRENTINO_RUNTIME_DIR $ENV{TRENTINO_HOME})
set (DEFAULT_INSTALL_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../)

if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
   set (CMAKE_INSTALL_PREFIX ${DEFAULT_INSTALL_PATH} CACHE STRING "Install path" FORCE)
endif()

##############################################################################
# 								COMPILER OPTIONS  							 #
##############################################################################
if(MSVC)
	add_definitions(-DUNICODE -D_UNICODE)
	add_definitions(/W4)
else()
	add_definitions(-Wall -pedantic)
endif()

##############################################################################
# 							   OUTPUT CONFIGURATION						     #
##############################################################################
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/build/${CMAKE_SYSTEM_PROCESSOR}${CMAKE_SYSTEM_NAME})
set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/build/${CMAKE_SYSTEM_PROCESSOR}${CMAKE_SYSTEM_NAME})



set(SCAAPI_INCLUDE_DIRS ${TRENTINO_RUNTIME_DIR}/include)
set(BOOST_INCLUDE_DIRS ${TRENTINO_RUNTIME_DIR}/include)
#source and header files
FILE (GLOB ${PNAME}_HEADER_FILES *.h *.inl
	  services/*.h services/*.inl)

FILE (GLOB ${PNAME}_SCA_FILES *.xml  *.componentType META-INF/*.xml META-INF/*.composite)
FILE (GLOB ${PNAME}_BINDING_SCA_FILES *.tidl.properties *.java)

FILE (GLOB ${PNAME}_SCA_COMPONENT_TYPES *.componentType )
FILE (GLOB ${PNAME}_SOURCE_FILES *.cpp services/*.cpp)
SET(${PNAME}_SCA_FILES ${${PNAME}_SCA_FILES} ${${PNAME}_SCA_COMPONENT_TYPES})
FILE(GLOB ${PNAME}_EXPORTED_HEADERS *.h *.inl)  
#libs
set( ${PNAME}_THIRD_PARTY_LIBS 
     )
	 
set( ${PNAME}_CUSTOM_LIBS 
     )
	 
set( ${PNAME}_SOURCE_FILES ${${PNAME}_SOURCE_FILES}
						  ${${PNAME}_HEADER_FILES} ${${PNAME}_SCA_FILES})

if (WIN32)
	add_definitions(-DHELLOWORLDREMOTE_EXPORTS)
endif()

if(MSVC_IDE)
	source_group("SCA Files" FILES ${${PNAME}_SCA_FILES})
endif()

include_directories(${SCAAPI_INCLUDE_DIRS} ${BOOST_INCLUDE_DIRS})

add_library(${PNAME} SHARED ${${PNAME}_SOURCE_FILES})
set(${PNAME}_INSTALL_DIR ${PNAME})
set_target_properties(${PNAME} PROPERTIES OUTPUT_NAME ${PNAME})
install(TARGETS ${PNAME} RUNTIME DESTINATION ${${PNAME}_INSTALL_DIR}
                         LIBRARY DESTINATION ${${PNAME}_INSTALL_DIR}
						 ARCHIVE DESTINATION ${${PNAME}_INSTALL_DIR})
install(DIRECTORY META-INF DESTINATION ${${PNAME}_INSTALL_DIR})
install(FILES ${${PNAME}_EXPORTED_HEADERS} ${${PNAME}_BINDING_SCA_FILES} ${${PNAME}_SCA_COMPONENT_TYPES} DESTINATION ${${PNAME}_INSTALL_DIR})



##############################################################################
#                           CUSTOM TARGET FOR VALIDATING AND GENERATING CODE BY TRENGEN#
##############################################################################
MY_CREATE_VALIDATE_GENERATE_INSTALL_TARGET(${${PNAME}_INSTALL_DIR} )


5.1.2.1.2. Define the HelloWorld remote interface

A remote application using the SCA Binding should be defined using an interface description language. Trentino default binding defines its own IDL called TIDL (Trentino IDL) that is derived from the CORBA IDL specification. More details about TIDL can found in the next chapter. A TIDL interface is defined in one or more .java classes. TIDL uses part of the java syntax to describe the interfaces. The use of the java syntax makes it easy to extend and parse the interface. It also makes it possible to write TIDL files using existing java editors. Create a file named HelloWord.java in HelloWorldRemote_Source. The file should have the following content:

package Trentino.Example.HelloWorldRemote;

//We should ALWAYS Import org.trentino.tidl.* in a TIDL file
import org.trentino.tidl.*;

/**
* HelloWord Service, receive hello world messages 
* and send wellcome to the client.
**/
public interface HelloWorld extends TInterface{

/**
* The server receive an Hello message and send a 
* wellcome message back to the client who sent 
* the message
* @param name: the name of the client who sent the message
* @return TString a welcome message
**/
TString hello(TString name);
}

Then create a configuration file that describes declare the interface. The configuration file is the entry point for code generators like Trengen, that would like to create C++ artifacts based on a given service definition. The configuration file name should be exactly the qualified name of the HelloWorld interface, without dot. A TIDL configuration file end with tidl.properties. In our case it is: TrentinoExampleHelloWorldRemoteHelloWorld.tidl.properties. It only contains the following line of code:

interface=./HelloWorld.java

5.1.2.1.3. Generate the C++ interface

Note

Important: Trengen relies on JDK and not only the JRE (Java Runtime Environment). Make sure that a JDK 1.6.X has been installed.

From the TIDL definition of Helloword, we then generate the corresponding C++ interface. This is done using Trengen. (See Chapter 4 to learn more about Trengen tool). In the command line type:


Trengen -gencppitf Path/to/HelloWorldRemote_Source

The generated artifact is a header file containing the generated interface definition.

5.1.2.1.4. Implement the HelloWordRemote interface.

Create a class named HelloWordImpl in a header file named TrentinoExampleHelloWorldRemoteHelloWordImpl.h and copy the following implementation into it.


#ifndef TrentinoExampleHelloWorldRemoteHelloWorldImplH
#define TrentinoExampleHelloWorldRemoteHelloWorldImplH
#ifdef WIN32
   #ifdef HELLOWORLDREMOTE_EXPORTS
      #define HELLOWORLDREMOTE_IMPORT_EXPORT __declspec(dllexport)
   #else
      #define HELLOWORLDREMOTE_IMPORT_EXPORT __declspec(dllimport)
   #endif //HELLOWORLDREMOTE_EXPORTS
   #else
      #define HELLOWORLDREMOTE_IMPORT_EXPORT
#endif //WIN32
//baseclass
#include "TrentinoExampleHelloWorldRemoteHelloWorld.h"


namespace Trentino{
namespace Example{
namespace HelloWorldRemote{

//forward declaration


 //**************************************************************************************
 //                                         HelloWorld
 //**************************************************************************************
 //! \brief implementation of helloword service
 //**************************************************************************************
class HELLOWORLDREMOTE_IMPORT_EXPORT HelloWorldImpl : public HelloWorld{
  //construction
public:
 HelloWorldImpl();
 virtual ~HelloWorldImpl();
  //services
public:
	virtual std::string hello (const std::string& name);
  
}; //class HelloWorld
} //namespace Trentino
} //namespace Example
} //namespace HelloWorldRemote

#endif //TrentinoExampleHelloWorldRemoteHelloWorldImplH

Create the corresponding C++ class TrentinoExampleHelloWorldRemoteHelloWordImpl.cpp and copy the following code into it.



#include "TrentinoExampleHelloWorldRemoteHelloWorldImpl.h"


using namespace Trentino::Example::HelloWorldRemote;

//class HelloWorldImpl

HelloWorldImpl::HelloWorldImpl()
{
}
HelloWorldImpl::~HelloWorldImpl()
{
}

std::string HelloWorldImpl::hello (const std::string& name)
{
  std::string result("Hello ");
  result+=name;
  return name;
}

5.1.2.1.5. Describe your HellowordRemote SCA contribution

Now our service is implemented (a C++ implementation is available), we need to create SCA component composite and contribution in other to describe our application and make it deployable into a Trentino runtime.

5.1.2.1.5.1. HelloWorld remote component

We start by defining our SCA component type which represents the configurable aspects of our implementation. A component type is described in a *.componentType xml document, that must be located in the same folder with the component implementation (the location of the component header file), in our case the component type name is TrentinoExampleHelloWorldRemoteHelloWordImpl.componentType. It has the following content:


<?xml version="1.0" encoding="utf-8"?>
<componentType xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912">
      <service name="HelloWorld" >
      <interface.cpp remotable="true" class="Trentino::Example::HelloWorldRemote::HelloWorld" header="TrentinoExampleHelloWorldRemoteHelloWorld.h"/>
    </service>
</componentType> 

Our component type defines the Helloword Service and C++ interface. The interface is defined to be remotable ("remotable" is Trentino's contribution to SCA. It is defined by Trentino). Since no binding is specified for the service, our default sca binding is assumed to be the one used for remote communication.

5.1.2.1.5.2. HelloWorld remote composite

Now we can create a composite that has one instance of our previously defined component type For that purpose Trentino requires composites to be located in a folder named META-INF. In our source folder, create META-INF folder and create an xml file named: HelloWorldRemote.composite (composite files always end with .composite), and paste following content into it:


<?xml version="1.0" encoding="utf-8"?>
<composite name="HelloWorldRemoteComposite" xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912" targetNamespace="HelloWorldRemoteNamespace">

  <component name="TrentinoExampleHelloWorldRemoteHelloWorldImpl">

    <implementation.cpp
        class="Trentino::Example::HelloWorldRemote::HelloWorldImpl"
		header="TrentinoExampleHelloWorldRemoteHelloWorldImpl.h"
        scope="composite"
		library="HelloWorldRemote" 
		eagerInit="true"/>
		<service name="HelloWorld" >
      <interface.cpp remotable="true" class="Trentino::Example::HelloWorldRemote::HelloWorld" header="TrentinoExampleHelloWorldRemoteHelloWorld.h"/>
    </service>
  </component>
</composite>

Our composite has a component that is an instance of TrentinoExampleHelloWorldRemoteHelloWorldImpl.componentType. The component is configured with our implementation. The location of the library containing the implementation is also defined.

5.1.2.1.5.3. HelloWorld contribution

The last step in your application description is to create a contribution that is an xml document that describes all the artifacts (the so-called deployable elements) to be deployed into and managed together by the runtime. For our simple case, the only available deployable element is the previously created composite and its dependencies (all componentTypes and compiled libraries). The name of the contribution file should be sca-contribution.xml and it should be created in our META-INF folder. Paste the following code into it:


<?xml version="1.0" encoding="utf-8"?>
<contribution xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912" xmlns:sample="HelloWorldRemoteNamespace">
<deployable composite="sample:HelloWorldRemoteComposite"/>
</contribution>

5.1.2.1.6. Compile the server application

We would like to do all these steps without an IDE but rather with a console.

  • If you are using windows, then please open your visual studio console.

  • Create a folder named HelloWorldRemote_Build next to HelloWorldRemote_Source

  • Change to the created directory : cd HelloWorldRemote_Build

  • Call Cmake: cmake ../ HelloWorldRemote_Source

  • Now your visual studio solution has been created (On linux your make files)

  • On windows call ‘msbuild INSTALL.vcxproj’ on linux just ‘make install’

  • This will create a folder named HelloWorldRemote next to HelloWorldRemote_Source. The HelloWorldRemote folder contains your compiled and ready for validation contribution

5.1.2.1.7. Code validation and generation

Before been deployed into the runtime, a prepared contribution as we did in the last steps will go through a complex validation and code generation process. The validation process make sure that only a consistent and specification conform contribution can be deployed into the runtime. To validate and generate code, type for windows:


msbuild [Trengen_Validate_Generate_Install].vcxproj

For linux, type:


make [Trengen_Validate_Generate_Install]

This last step update your contribution by creating a new library called sca-contribution (.dll or .so). The created library is located in the META-INF folder of your contribution. To further understand what is done during the last step, you can take a look on the custom target [Trengen_Validate_Generate_Install] defined in our cmake file

5.1.2.2. Create the HelloWorld client application

The steps for creating the client applications are similar to the ones for the server application Please download the source code for the client from our samples examples. And build as described for the server example.

The client application is a component that is initialized directly after deployment (eager initialization). It references the HelloWorld Service created before. It has an initialisation lifecycle method that is called as soon as the component is initialized. That lifecycle method just connects to the HelloWord Server and calls the remote HelloWord Service. Here is the source code of the HelloWorldClient



#include <iostream>
#include "TrentinoExampleHelloWorldRemoteHelloWorldClientImpl.h"


using namespace Trentino::Example::HelloWorldRemote;

//class HelloWorldClientImpl

HelloWorldClientImpl::HelloWorldClientImpl()
{
}
HelloWorldClientImpl::~HelloWorldClientImpl()
{
}

void HelloWorldClientImpl::setHelloWorld(HelloWorld* helloWorld){
mHelloWorld = helloWorld;
callHello();
}

//This method is called by the Runtime as soon as this component is initialized
void HelloWorldClientImpl::callHello ()
{

  try
  {
      std::string name("Trentino");
      std::string response = mHelloWorld->hello(name);
      std::cout << "Remote HelloWorld Service called. Response is:" << response << std::endl;
  }
  catch (std::exception& e)
  {
  	 std::cout << "Exception during call of hello world:" << e.what() << std::endl;
    return;
  }

}

5.1.2.3. Deploy and run

In this last step start two different instances of the Trentino runtime. In the first instance, deploy the server and wait until the server deployment is completed. In the second instance, deploy the client. The client will print:


Remote HelloWorld Service called. Response is: Hello Trentino

5.1.3. Binding-related generated files

For the server side, the files generated by Trengen can be seen in the following figure:

server-side generated files

server-side generated files

For the client side, the files generated by Trengen can be seen in the following figure:

client-side generated files

client-side generated files

  • ProtobufMessages, Request, Response and Types are common for both client and server. They are the generated protobuf files. Here are the reasons why we use google-protobuf in Trentino:

    • Protobuf is small in size - efficient data storage (far smaller than xml).

    • Protobuf is cheap to process - both at the client and server.

    • Protobuf is platform independent - portable between different programming architectures.

    • Protobuf is extensible - to add new data to old messages.

    • Protobuf is fast.

  • TrentinoGenModelLoader, TrentinoGenProxiesWrappers and TrentinoGenReflx files are also common for both client and server:

    • TrentinoGenModelLoader: contains code responsible for creating the in-memory SCA Model by instantiating SCA Model classes. The created object graph reflects all the information specified in SCDL artifacts in the contribution. It implementes Trentino::Gen::GenContributionInfo::loadModel(). The instantiation doesn‘t happen automatically when sca-contribution.dll is loaded but is triggered by the runtime through a call to the loadModel() function.

    • TrentinoGenProxiesWrappers: Proxies keeps references-related information and wrappers keeps services related information. This is the bridge between invocation and business logic. It includes service header files (mentioned in interface.cpp/@header): this is necessary because proxies inherit service classes and wrappers call methods of the service classes.

    • TrentinoGenReflx: contains reflection code for all the implementation classes in the contribution. It includes headers of the implementation classes (mentioned in implementation.cpp/@header): this is necessary because the generated reflection code uses symbols (methods, types) defined in the business logic code.

  • TrentinoGenBindingProxy is generated in client side. It creates a protobuf request message, sends it to ClientProxyDelegate, gets the response, parses the response from string and finally returns the response.

  • TrentinoGenSCABindingHelpers is generated in server-side. It deserializes the request and serializes the response.

  • BeanUtils is generated in both client and server. It makes the conversion between java types and protobuf types. It is used in TrentinoGenSCABindingHelpers and TrentinoGenBindingProxy.

5.1.4. Binding.sca from development point of view

The following diagram represents the sequence of binding in Trentino. It covers the "boot", "install server" and "install client" commands.

Sequence diagram for binding SCA

Sequence diagram for binding SCA

After "boot" command, BootsTrapper is called. It creates instances of Binding Manager, Contribution Loader, ComponentCPPImpl Manager, ComponentProperty Manager and Invocation Layer.

After "install _name_of_the_server_contribution_" command, onDeploy() function of BindingManager is called. This is the start of Binding in Trentino.

  • Binding Manager creates Binding Factory.

  • BindingFactory gets SCABindingFactory.

  • SCABindingFactory creates BindingSCA.

  • BindingManager calls createBinding() method of SCABindingFactory. Then doCreateBinding() function of BindingSCA is called by SCABindingFactory.

  • BindingFactory calls start() method of BindingFactory. Then start() function of BindingSCA is called by BindingFactory.

  • BindingSCA creates instances of SCAContext, BindingSCADataHandler, ZMQServer and InvokerProxy. Then it calls start() function of ZMQServer.
    Zero MQ is the socket library that acts as a concurrency framework. Trentino uses Zero MQ for the message passing(serialization and deserialization included) via network.



After "install _name_of_the_client_contribution_" command, onInit() or getInstance() function of ComponentCPPImplManager is called (This is decided by the configuration in SCDL).

  • ComponentCPPImplManager creates an instance of Component Implementation of Caller (this is business logic provided by end-user. It is TrentinoExampleHelloWorldRemoteHelloWordImpl in our sample.)

  • Component Implementation object calls a service method which is defined also in Proxy. (Proxy is a generated file.)

  • Proxy invokes Invocation Layer.

  • Invocation Layer calls invoke() function of Wrapper. (Wrapper is also a generated file)

  • Wrapper calls the related service method which is in BindingProxy. (BindingProxy is a generated file)

  • BindingProxy calls send() function of ClientProxyDelegate.

  • ClientProxyDelegate calls send() function of ClientProxyDelegateImpl. ClientProxyDelegateImpl sends the request and gets the related response.



After a request is received in server side, handle() function of BindingSCADataHandler by ZMQServer.

  • BindingSCADataHandler calls the deserializeRequest() function of BindingHelpers. (BindingHelper is a generated file)

  • BindingSCADataHandler serializes the response and sends it via network.

5.2. Trentino IPC Binding

5.2.1. Overview

Inter-process communication (IPC) is a set of methods for the exchange of data among multiple threads in one or more processes. IPC methods are divided into methods for

  • message queues,

  • synchronization,

  • shared memory, and

  • remote procedure calls (RPC).

RPC is not in the scope of this binding type. Because other binding types (binding SCA, bacnet binding etc…) are kinds of RPC. Message queues and shared memory are our focus for IPC binding in Trentino.

Each thread has its own private memory which is not accessible to other threads. Each thread may want to access a shared memory for fast communication.

There can be more than one Trentino runtime running on the same computer. The reason why the end-user has 2 or more Trentinos running in the same computer is that customer may want to isolate services from each other.

5.3. Extending bindings in Trentino (using TIDL / IDL)

Binding Framework is a set of interfaces, guidelines and documentation that enables a user not directly involved in Trentino development to extend Trentino with additional Bindings. Siemens develops the core and Trentino users are supposed to develop Bindings as needed.

The goal for Binding Framework was to keep it as easy as possible to extend. Thus binding framework in Trentino is a generic module. Extending bindings requires:

  • New .xsd for new binding (in the SCDL part)
    For example: binding.ipc is not specified in SCA. A new xsd for the binding.ipc should be defined.

  • Update the SCA model (model in Java part).
    For example: binding.ipc is not specified in SCA. So the new elements (like uri attribute for binding.ipc) should be added to the SCA Java model.

  • Changes should be reflected to SCAMirrorModel (in Java part) and SCA C++ model.

  • Change the runtime model.

  • Make the Binding Layer support the new binding (adapt the new Runtime model binding attributes etc...).

  • New binding should be reflected to generated ModelLoader file. (in java part)

  • Decide your TIDL for interfacing (it is explained in chapter-6).

  • If serialization/deserialization between runtimes is needed, message passing format should be specified and related data converter structures should be generated. For the conversion, BeanUtils (for both server and client side) generation should also be enabled.


    For example: In binding.sca we used BeanUtils for converting c++ objects to protobuf objects and vice versa.
  • BindingProxy (for client side) and BindingHelpers(for server side) are obligatory classes. Contents may differ. They must be iplemented in every binding. They are the bridges between business logic code and Trentino runtime.

Chapter 6. Trentino Interface description language (TIDL) reference

6.1. Overview

The Trentino Interface description language is used to describe remotable Services by the Trentino SCA (default) binding. The interface has the same concepts as corba IDL, but use the java language to describe services. Using the java language to describe our (C++) interface has many advantages.

  • We can reuse existing IDE when creating our interface

  • We rely on a robust java JDK for parsing the IDL

  • Reuse existing java knowledge

6.2. Why do we need TIDL?

  1. To be interoperable. TIDL is neutral and we can use it to generate code for other Languagues like java (e.g used by Management and monitoring tool to acces a runtime).
    Example: Android client

  2. In TIDL we can put more Interface description information than in normal C++ code
    Example: Complex addressing where the response to a request should be send to more than one recipient
    Example: metadata to set time out for a method

  3. Semantic of remote procedural call migth be difficult to implement by hand.
    Example : Interface methods should not use pointers
    Example : Data binding: only legal data structures have to be exchanged -Y user have to learn format of leagl data structure. Trengen have to be able to sucessfully serialize all deta created by the end user

  4. Parsing issue: The CPP Parser is not well tested and the functionality covered until now, is missing some important features
    Example: MACROS expansion

  5. Extensibililty: extends the framework by extending the TIDL while the generated interface is not changed.

6.3. Example interface


package Trentino.Example.BasicCalculatorRemote;

//We MUST ALWAYS Import this package
import org.trentino.tidl.*;

public interface BasicCalculator extends TInterface{

	ComplexNumber add(ComplexNumber a, ComplexNumber b);
	
	TInt addSimple(TInt a, TInt b);
	
	ComplexNumber divide(ComplexNumber a, ComplexNumber b);
	
	void multiply(ComplexNumber a, ComplexNumber b,@Out ComplexNumber c);
	
	ComplexNumber divide2 (TupleComplexNumber tuple);
	
	TUInt calculateAge (Person person) throws ValidationException;
	
	
	class ValidationException extends TException{
     TString details;
    }
	 
	class Address extends TStruct{
	  TString street;
	  Phone phone;
	}
	
	class TupleComplexNumber extends TStruct{
		ComplexNumber a;
		ComplexNumber b;
	}
	
	class Phone extends TStruct{
	TString home;
	TString mobile;
	}
	
	class Person extends TStruct{
		Address addres;
		TString name;
		TString surname;
		Person mother;
     }
	 
	 class ComplexNumber extends TStruct{
		TInt a;
		TInt b;
     }
}


The description of the interface is self explanatory for a java developer. An interface extends "TInterface" and has methods. An interface can import types.

6.4. TIDL types

TIDL support simple and complex types. All TIDL simple types are prefixed with "T", to differentiate them from other java types.

6.4.1. Simple types

  • TBool: the boolean type

  • TDouble: the double type

  • TFloat: the float type

  • TInt: the int type. TInt is mapped to int32 C++ type

  • TUInt: unsigned int type: mapping uint32

  • TLong: the long type: mapping int64

  • TULong: the long type: mapping uint64

  • TString: represent a string, mapping a C++ std::string

6.4.2. Complex types

Complex types are defined by creating a class that extends "TStruct" or that extends another complex type. A complex type defines all the fields it contains. The fields MUST be TIDL simples types or TIDL complex types. Inheritance is supported for complex types. A complex type can reference a object from the same type.

Example 6.1. 


	 class Person extends TStruct{
		Address addres;
		TString name;
		TString surname;
		Person mother;
     }


6.4.3. Exceptions

TIDL support exception specification. An exception is a TIDL complex type with the particularity that it extends "TException" instead of "TStruct"


	class ValidationException extends TException{
     TString details;
    }
	 

6.5. Interface

An interface is a java interfaces, with the exception that a TIDL interface always extends "TInterface". It is described in a java file with the same name.

6.5.1. Import section

A TIDL interface MUST allways import org.trentino.tidl.*; This import statement will import all the basic TIDL types and annotations in the TDIL description file.

6.5.2. Interface Methods

Interfaces methods are normal java methods. All the types used by a TIDL methods as arguments or return types MUST be TIDL types. Normal java types like "String", "int" are not used and will cause the compilation and code generation to fails. Exceptions can be specified on methods. In that case, exception MUST be a TIDL exception.

6.5.3. Methods arguments

Methods arguments can be annotated to describe their behaviour.


void multiply(ComplexNumber a, ComplexNumber b,@Out ComplexNumber c);

6.5.3.1. @In Annotation

@In annotation indicates that the parameter is an input parameter. So that it should not be modified.

A Parameter without annotation is supposed to be @In annotated

6.5.3.2. @Out annotation

@Out indicate that the given parameter is an output parameter, that should be filled by the service with data. It is therefore modifiable.

6.5.3.3. @InOut annotation

This annotation indicates that the parameter is an input but also output parameter. The service is supposed to read data from that parameter but also write to it back.

6.6. C++ code generation

Trengen can generate C++ code from a TIDL Interface. The generated code is used to implement the client and the server. See the trengen chapter (usage) for more details about the C++ code generation from TIDL interfaces.

6.6.1. Example generated C++ code

This is the corresponding C++ code generated for the BasicCalculator interface specified in the last section


// Generated by Trentino TDIL CPP interface generator. do not modify

#ifndef TrentinoExampleBasicCalculatorRemoteBasicCalculatorH
#define TrentinoExampleBasicCalculatorRemoteBasicCalculatorH

#include "BasicCalculatorGlobal.h"
#ifndef NULL
#define NULL 0
#endif


#include <boost/cstdint.hpp>
#include <string>

typedef  boost::int32_t  tint32_t;
typedef  boost::uint32_t  tuint32_t;
typedef  boost::int64_t  tint64_t;
typedef  boost::uint64_t  tuint64_t;

namespace Trentino{
namespace Example{
namespace BasicCalculatorRemote{

//forward declaration
class ComplexNumber;
class Phone;
class Address;
class Person;
class TupleComplexNumber;
class ValidationException;


//**************************************************************************************
//                                         ComplexNumber
//**************************************************************************************
//! \brief 
//**************************************************************************************
class TRENTINO_EXAMPLE_BASICCALCULATORREMOTE_IMPORT_EXPORT ComplexNumber{
private:
	tint32_t a_;
	tint32_t b_;

public:
// constructor and destructor---------------------------------------
	ComplexNumber();
	virtual ~ComplexNumber();
// default instance
   static const ComplexNumber& default_instance();
// accessors -------------------------------------------------------
	void set_a(tint32_t value);
	tint32_t a() const; 
	void set_b(tint32_t value);
	tint32_t b() const; 
 
 //default instance data
 private:
   static ComplexNumber* default_instance_;
}; //class ComplexNumber

//**************************************************************************************
//                                         Phone
//**************************************************************************************
//! \brief 
//**************************************************************************************
class TRENTINO_EXAMPLE_BASICCALCULATORREMOTE_IMPORT_EXPORT Phone{
private:
	std::string* home_;
	std::string* mobile_;

public:
// constructor and destructor---------------------------------------
	Phone();
	virtual ~Phone();
// default instance
   static const Phone& default_instance();
// accessors -------------------------------------------------------
 	const std::string& home() const;
 	void set_home(const std::string& value);
	void set_home(const char* value);
	void set_home(const char* value, size_t size);
 	const std::string& mobile() const;
 	void set_mobile(const std::string& value);
	void set_mobile(const char* value);
	void set_mobile(const char* value, size_t size);
 
 //default instance data
 private:
   static Phone* default_instance_;
}; //class Phone

//**************************************************************************************
//                                         Address
//**************************************************************************************
//! \brief 
//**************************************************************************************
class TRENTINO_EXAMPLE_BASICCALCULATORREMOTE_IMPORT_EXPORT Address{
private:
	std::string* street_;
	Phone* phone_;

public:
// constructor and destructor---------------------------------------
	Address();
	virtual ~Address();
// default instance
   static const Address& default_instance();
// accessors -------------------------------------------------------
 	const std::string& street() const;
 	void set_street(const std::string& value);
	void set_street(const char* value);
	void set_street(const char* value, size_t size);
	Phone* mutable_phone();
	Phone& phone() const;
	bool has_phone() const;
 
 //default instance data
 private:
   static Address* default_instance_;
}; //class Address

//**************************************************************************************
//                                         Person
//**************************************************************************************
//! \brief 
//**************************************************************************************
class TRENTINO_EXAMPLE_BASICCALCULATORREMOTE_IMPORT_EXPORT Person{
private:
	Address* addres_;
	std::string* name_;
	std::string* surname_;
	Person* mother_;

public:
// constructor and destructor---------------------------------------
	Person();
	virtual ~Person();
// default instance
   static const Person& default_instance();
// accessors -------------------------------------------------------
	Address* mutable_addres();
	Address& addres() const;
	bool has_addres() const;
 	const std::string& name() const;
 	void set_name(const std::string& value);
	void set_name(const char* value);
	void set_name(const char* value, size_t size);
 	const std::string& surname() const;
 	void set_surname(const std::string& value);
	void set_surname(const char* value);
	void set_surname(const char* value, size_t size);
	Person* mutable_mother();
	Person& mother() const;
	bool has_mother() const;
 
 //default instance data
 private:
   static Person* default_instance_;
}; //class Person

//**************************************************************************************
//                                         TupleComplexNumber
//**************************************************************************************
//! \brief 
//**************************************************************************************
class TRENTINO_EXAMPLE_BASICCALCULATORREMOTE_IMPORT_EXPORT TupleComplexNumber{
private:
	ComplexNumber* a_;
	ComplexNumber* b_;

public:
// constructor and destructor---------------------------------------
	TupleComplexNumber();
	virtual ~TupleComplexNumber();
// default instance
   static const TupleComplexNumber& default_instance();
// accessors -------------------------------------------------------
	ComplexNumber* mutable_a();
	ComplexNumber& a() const;
	bool has_a() const;
	ComplexNumber* mutable_b();
	ComplexNumber& b() const;
	bool has_b() const;
 
 //default instance data
 private:
   static TupleComplexNumber* default_instance_;
}; //class TupleComplexNumber

//**************************************************************************************
//                                         ValidationException
//**************************************************************************************
//! \brief 
//**************************************************************************************
class TRENTINO_EXAMPLE_BASICCALCULATORREMOTE_IMPORT_EXPORT ValidationException{
private:
	std::string* details_;

public:
// constructor and destructor---------------------------------------
	ValidationException();
	virtual ~ValidationException();
// default instance
   static const ValidationException& default_instance();
// accessors -------------------------------------------------------
 	const std::string& details() const;
 	void set_details(const std::string& value);
	void set_details(const char* value);
	void set_details(const char* value, size_t size);
 
 //default instance data
 private:
   static ValidationException* default_instance_;
}; //class ValidationException

//**************************************************************************************
//                                         BasicCalculator
//**************************************************************************************
//! \brief 
//**************************************************************************************
class BasicCalculator{
  //services
public:
	virtual ComplexNumber add (const ComplexNumber& a,const ComplexNumber& b) =0;
	virtual tint32_t addSimple (const tint32_t a,const tint32_t b) =0;
	virtual ComplexNumber divide (const ComplexNumber& a,const ComplexNumber& b) =0;
	virtual void multiply (const ComplexNumber& a,const ComplexNumber& b, ComplexNumber& c) =0;
	virtual ComplexNumber divide2 (const TupleComplexNumber& tuple) =0;
	virtual tuint32_t calculateAge (const Person& person) throw (ValidationException)=0;
  
}; //class BasicCalculator
} //namespace Trentino
} //namespace Example
} //namespace BasicCalculatorRemote

#endif //TrentinoExampleBasicCalculatorRemoteBasicCalculatorH

6.6.2.  Providing default values at model level

Default values for structures can be defined in a TIDL using the @Default annotation.



public interface ICommandService extends TInterface{

    TBool isRunning();
	StorageRackData getStateData();
	
   void setCommand(Command command);
   void setCommandWithIdentifier(TString identifier, Command command);
   
   class StorageRackCommand extends TStruct {
        TFloat activePower;
        TFloat reactivePower;  
   }
   
   class Data extends TStruct{
   
        @Default(bv=true)
		TBool isValid;
		
		@Default(sv="Default")
		TString Name;
		   
		@Default(nv=-1)
		TFloat StateOfCharge;
		
		@Default(nv=-1)
		TFloat MaxChargingPower;
   }
}


The @Default annotation has tree attributes.

  • nv (Number Values): used to store default values for numbers. Example: @Default(nv=-1)

  • sv (String Values): used to store default values for strings. Example: @Default(sv="Default")

  • bv (Boolean Values): used to store default values for boolean. Example: @Default(bv=true)

Note

Only fields with primitives types can have default values. Putting default values on complex types has no effect during code generation.

Chapter 7. Trentino Service Discovery

The goal of service discovery is to locate the appropriate services for a reference, if the reference hasn't define its target service explicitly by using one of the methods mentioned under SCA specification, section 4.3.1. Currently service discovery applies to remote services. By using service discovery a component can locate referenced services that are hosted on other Trentino runtimes in the same network. Remote service discovery identifies the matching service and its connection specific information to make remote communication possible. Service discovery is restricted to a local area network.

7.1. Reference and Service Wiring with Service Discovery

For remote references (@remotable/interface.cpp/reference = true) service discovery is triggered if no connection specifier attribute is defined for the bindings of the reference.(i.e. for binding.sca service discovery is triggered if uri attribute is not specified) (see Item-2 under SCA specification section 4.3.1) Service discovery matches the services that qualify the following conditions:

  • Services should have the same fully qualified interface class name(@class/interface.cpp).
  • Services should support at least one of the bindings supported by the reference.
  • Services should support the metadata specified by the reference.


In addition to SCA assembly schema version 1.1. Trentino defines an sca:Metadata element which is part of sca:Contract element to be able to describe extra characteristics of services and references. The following snippet shows the pseudo-schema of a reference and a service that hosts metadata.


<!-- metadata schema snippet -->
<composite ... >
...
  <service ... >
   <metadata>
     <stringAttributes name="xs:string" value="xs:string"/>
   </metadata>
   <interface ... />
    <binding uri="xs:anyURI"? name="xs:NCName"? requires="list of xs:QName"?policySets="listof xs:QName"?>
     <wireFormat/>
     <operationSelector/>
     <requires/>
     <policySetAttachment/>
    </binding>
    <callback>
     <binding uri="xs:anyURI"? name="xs:NCName"? requires="list of xs:QName"? policySets="list of xs:QName"?>
      <wireFormat/>
      <operationSelector/>
      <requires/>
      <policySetAttachment/>
     </binding>
    </callback>
  </service>
  <reference ... >
   <metadata>
     <stringAttributes name="xs:string" value="xs:string"/>
   </metadata>
   <interface ... />
    <binding uri="xs:anyURI"? name="xs:NCName"? requires="list of xs:QName"?policySets="listof xs:QName"?>
     <wireFormat/>
     <operationSelector/>
     <requires/>
     <policySetAttachment/>
    </binding>
    <callback>
     <binding uri="xs:anyURI"? name="xs:NCName"? requires="list of xs:QName"? policySets="list of xs:QName"?>
      <wireFormat/>
      <operationSelector/>
      <requires/>
      <policySetAttachment/>
     </binding>
    </callback>
  </reference>
</composite>

 

Example: The following SCDL is an example of a reference that will be wired via service discovery.


		<reference name="BasicPrinterRef">
			<metadata>
				<stringAttributes name="colour" value="yellow"/>
			</metadata>
			<interface.cpp class="Trentino::Example::BasicPrinter" header="services/TrentinoExampleBasicPrinter.h" remotable="true"/>
			<binding.sca/>
		</reference>

 

As the service below supports binding.sca by default, and as it has matching interface and metadata, it is wired to the reference above:


	<service name="BasicPrinter" >
		<metadata>
			<stringAttributes name="floor" value="3"/>
			<stringAttributes name="colour" value="yellow"/>
		</metadata>
        <interface.cpp class="Trentino::Example::BasicPrinter" header="services/TrentinoExampleBasicPrinter.h" remotable="true"/>
    </service>

 

Eventually service discovery provides the binding specific information of the found service. Namely the connection information required for the binding types supported by the found service. (i.e. for binding.sca uri that includes network address, port information of the service is provided ) So runtime can manage the remote communication with this binding communication information. If there are more than one matching services matching, runtime uses one of them randomly.

7.2. Enabling and Configuring Service Discovery

7.2.1. Service Discovery Configuration in Runtime.conf

Service discovery is enabled or partially configured in the Runtime.conf file. Trentino uses OpenSLP for service discovery please also refer at the OpenSLP configuration mentioned under the respective section below. The user can enable or disable service discovery for a Trentino runtime. In the Trentino configuration file Runtime.conf, the following options should be available.

[Service_Discovery]
# Default to true
#default to true
enable.remote.service.discovery=true

In case of a discovery failure, the service state should be NOT_AVAILABLE. The runtime MUST be configured to try discovery a number of time if discovery fails. The time interval and the number of retries are configurable in Runtime.conf.

[Service_Discovery]
#default to false
discovery.max.retry=3
#values in seconds
discovery.retry.interval=10

7.2.2. OpenSLP and its configuration

Trentino uses OpenSLP for service discovery.
http://www.openslp.org/

Service Location Protocol (SLP) is an Internet Engineering Task Force (IETF) standards track protocol that provides a framework to allow networking applications to discover the existence, location, and configuration of networked services in enterprise networks.

The OpenSLP project is an effort to develop an open-source implementation of the IETF Service Location Protocol suitable for commercial and non-commercial application.

Errors that are detected at network by OpenSLP are logged or notified with error codes of OpenSLP. For the meanings of error codes please see Appendix-B.

7.2.2.1. OpenSLP configuration file

slp.conf is the configuration used by OpenSLP. Some of these parameters hame more vital importance based on the network conditions. Default version of this configuration file is comes with Trentino installation. For a local area network that has Trentino runtimes operating, to have service discovery function available, at least one of Trentino runtimes must play the role of directory agent (SLP terminology, for further information please check out OpenSLP documentation or SLP RFC-2608). So for each LAN the user needs to set net.slp.isDA to true for at least one Trentino runtime, to have service discovery feature work. User might be potentially be interested in the following attributes:

  • net.slp.isDA: Enables slpd to function as a DA. Only a very few DAs should exist. In Trentino it is true.
  • slp.watchRegistrationPID: If net.slp.watchRegistrationPID is set to true, local registrations made with the SA via the SLPReg() API call will be monitored. If the PID of the process (and/or thread on Linux) disappears (the registering process died unexpectedly with out calling SLPDereg()), then the registration is automatically de-registered. (Default is is false in Trentino)
  • net.slp.unicastMaximumWait: An integer giving the maximum amount of time (in milliseconds) to perform unicast requests.(Default is is 50000 ms or 50 secs in Trentino)
  • net.slp.multicastMaximumWait: An integer giving the maximum amount of time (in milliseconds) to perform multicast requests (Default is 50000 ms or 50 secs, in Trentino).


The user might need to change other configuration parameters based on the specific needs of networks and in such a case user should refer at the descriptions of configuration parameters in the config file or at the web site of openSLP. http://www.openslp.org/

Chapter 8. configuration before contribution deployment

8.1. Editing sca-contribution.xml before deployment

In real world applications, the contribution compilation, including validation and code generation often takes place in a non productive system. Many contributions can have common dependencies to a set of libraries. Those shared libraries are typically not in the contribution itself, but are in a separate folder. To enable Trentino runtime to find external dependencies to a contribution, the user must specify the DLL folder in sca-contribution.xml . Example:


<contribution xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912" xmlns:ss="MyNamespace">
   <deployable composite="ss:MyComposite"/>
   <import.cpp name="dll-directory" location="../bin" />
</contribution>

The tag import.cpp MUST have the name dll-directory. The required location can be relative to the contribution root folder or absolute. We recommend using a relative value since it is more portale

8.2. Changing dll-directory at install time

In extreme case, the dll-directory might be different from device to device. The user still have the possibility to set the dll-directory witout having to rebuild the contribution. In the META-INF directory, open the file sca-contribution.conf and add the following line at the end of the file:


dir=<absolute/or relative/ path to the/ dll directory >

The runtime will not load your contribution if the given directory does not exists.

Appendix Appendix A. Validated SCA constraints

  • [ASM40001]: The extension of a componentType side file name MUST be .componentType

  • [ASM40003] The @name attribute of a service child element of a componentType MUST be unique amongst the service elements of that componentType.

  • [ASM40004] The @name attribute of a reference child element of a componentType MUST be unique amongst the reference elements of that componentType.

  • [ASM40005] The @name attribute of a property child element of a componentType MUST be unique amongst the property elements of that componentType.

  • [ASM40007] The value of the property @type attribute MUST be the QName of an XML schema type.

  • [ASM40010] A single property element MUST NOT contain both a @type attribute and an @element attribute

  • [ASM40011] When the componentType has @mustSupply="true" for a property element, a component using the implementation MUST supply a value for the property since the implementation has no default value for the property.

  • [ASM50001]: The @name attribute of a component child element of a composite MUST be unique amongst the component elements of that composite.

  • [ASM50002] The @name attribute of a service element of a component MUST be unique amongst the service elements of that component.

  • [ASM50003] The @name attribute of a service element of a component MUST match the @name attribute of a service element of the componentType of the implementation child element of the component.

  • [ASM50004] If an interface is declared for a component service, the interface MUST provide a compatible subset of the interface declared for the equivalent service in the componentType of the implementation

  • [ASM50007] The @name attribute of a service element of a component MUST be unique amongst the service elements of that component

  • [ASM50008] The @name attribute of a reference element of a component MUST match the @name attribute of a reference element of the componentType of the implementation child element of the component.

  • [ASM50009] The value of multiplicity for a component reference MUST only be equal or further restrict any value for the multiplicity of the reference with the same name in the componentType of the implementation, where further restriction means 0..n to 0..1 or 1..n to 1..1.

  • [ASM50010] If @wiredByImpl="true" is set for a reference, then the reference MUST NOT be wired statically within a composite, but left unwired.

  • [ASM50013] If @wiredByImpl="true", other methods of specifying the target service MUST NOT be used.

  • [ASM50014] If @autowire="true", the autowire procedure MUST only be used if no target is identified by any of the other ways listed above. It is not an error if @autowire="true" and a target is also defined through some other means, however in this case the autowire procedure MUST NOT be used.

  • [ASM50026] If a reference has a value specified for one or more target services in its @target attribute, there MUST NOT be any child binding elements declared for that reference

  • [ASM50027] If the @value attribute of a component property element is declared, the type of the property MUST be an XML Schema simple type and the @value attribute MUST contain a single value of that type.

  • [ASM50028] If the value subelement of a component property is specified, the type of the property MUST be an XML Schema simple type or an XML schema complex type.

  • [ASM50029] If a component property value is declared using a child element of the property element, the type of the property MUST be an XML Schema global element and the declared child element MUST be an instance of that global element.

  • [ASM50031] The @name attribute of a property element of a component MUST be unique amongst the property elements of that component.

  • [ASM50032] If a property is single-valued, the value subelement MUST NOT occur more than once.

  • [ASM50033] A property value subelement MUST NOT be used when the @value attribute is used to specify the value for that property.

  • [ASM50034] If any "wire" element with its @replace attribute set to "true" has a particular reference specified in its @source attribute, the value of the @target attribute for that reference MUST be ignored and MUST NOT be used to define target services for that reference

  • [ASM50035] A single property element MUST NOT contain both a @type attribute and an @element attribute.

  • [ASM50036] The property type specified for the property element of a component MUST be compatible with the type of the property with the same @name declared in the component type of the implementation used by the component. If no type is declared in the component property element, the type of the property declared in the componentType of the implementation MUST be used.

  • [ASM50037] The @name attribute of a property element of a component MUST match the @name attribute of a property element of the componentType of the implementation child element of the component.

  • [ASM50038] In these cases where the types of two property elements are matched, the types declared for the two "property" elements MUST be compatible.

  • [ASM50039] A reference with multiplicity 0..1 MUST have no more than one target service defined.

  • [ASM50040] A reference with multiplicity 1..1 MUST have exactly one target service defined.

  • [ASM50041] A reference with multiplicity 1..n MUST have at least one target service defined.

  • [ASM50042] If a component reference has @multiplicity 0..1 or 1..1 and @nonOverridable==true, then the component reference MUST NOT be promoted by any composite reference.

  • [ASM50044] When a property has multiple values set, all the values MUST be contained within a single property element.

  • [ASM60001]: A composite @name attribute value MUST be unique within the namespace of the composite.

  • [ASM60002] @local="true" for a composite means that all the components within the composite MUST run in the same operating system process.

  • [ASM60003] The name of a composite service element MUST be unique across all the composite services in the composite.

  • [ASM60004] A composite service element's @promote attribute MUST identify one of the component services within that composite.

  • [ASM60005] If a composite service interface is specified it MUST be the same or a compatible subset of the interface provided by the promoted component service.

  • [ASM60006] The name of a composite "reference" element MUST be unique across all the composite references in the composite.

  • [ASM60007] Each of the URIs declared by a composite reference's @promote attribute MUST identify a component reference within the composite.

  • [ASM60008] the interfaces of the component references promoted by a composite reference MUST be the same, or if the composite reference itself declares an interface then each of the component reference interfaces MUST be a compatible subset of the composite reference interface..

  • [ASM60011] The multiplicity of a composite reference MUST be equal to or further restrict the multiplicity of each of the component references that it promotes, with the exception that the multiplicity of the composite reference does not have to require a target if there is already a target on the component reference. This means that a component reference with multiplicity 1..1 and a target can be promoted by a composite reference with multiplicity 0..1, and a component reference with multiplicity 1..n and one or more targets can be promoted by a composite reference with multiplicity 0..n or 0..1.

  • [ASM60012] If a composite reference has an interface specified, it MUST provide an interface which is the same or which is a compatible superset of the interface(s) declared by the promoted component reference(s).

  • [ASM60013] If no interface is declared on a composite reference, the interface from one of its promoted component references MUST be used for the component type associated with the composite.

  • [ASM60014] The @name attribute of a composite property MUST be unique amongst the properties of the same composite.

  • [ASM60031] The SCA runtime MUST raise an error if the composite resulting from the inclusion of one composite into another is invalid.

  • [ASM60032] For a composite used as a component implementation, each composite service offered by the composite MUST promote a component service of a component that is within the composite.

  • [ASM60033] For a composite used as a component implementation, every component reference of components within the composite with a multiplicity of 1..1 or 1..n MUST be wired or promoted.

  • [ASM60034] For a composite used as a component implementation, all properties of components within the composite, where the underlying component implementation specifies "mustSupply=true" for the property, MUST either specify a value for the property or source the value from a composite property.

  • [ASM60035] All the component references promoted by a single composite reference MUST have the same value for @wiredByImpl.

  • [ASM60036] If the @wiredByImpl attribute is not specified on the composite reference, the default value is "true" if all of the promoted component references have a wiredByImpl value of "true", and the default value is "false" if all the promoted component references have a wiredByImpl value of "false". If the @wiredByImpl attribute is specified, its value MUST be "true" if all of the promoted component references have a wiredByImpl value of "true", and its value MUST be "false" if all the promoted component references have a wiredByImpl value of "false".

  • [ASM60037] include processing MUST take place before the processing of the @promote attribute of a composite reference is performed.

  • [ASM60038] include processing MUST take place before the processing of the @promote attribute of a composite service is performed.

  • [ASM60039]include processing MUST take place before the @source and @target attributes of a wire are resolved.

  • [ASM60040] A single property element MUST NOT contain both a @type attribute and an @element attribute.

  • [ASM60041] If the included composite has the value true for the attribute @local then the including composite MUST have the same value for the @local attribute, else it is an error.

  • [ASM60042] The @name attribute of an include element MUST be the QName of a composite in the SCA Domain.

  • [ASM60043] The interface declared by the target of a wire MUST be a compatible superset of the interface declared by the source of the wire.

  • [ASM60045] An SCA runtime MUST introspect the componentType of a Composite used as a Component Implementation following the rules defined in the section "Component Type of a Composite used as a Component Implementation"

  • [ASM60047] If there is no component service with @name corresponding to service-name, the SCA runtime MUST raise an error.

  • [ASM60048] If service-name is not present, the target component MUST have one and only one service with an interface that is a compatible superset of the wire source’s interface and satisifies the policy requirements of the wire source, and the SCA runtime MUST use this service for the wire.

  • [ASM60049] If binding-name is present, the binding subelement of the target service with @name corresponding to binding-name MUST be used for the wire.

  • [ASM60050] If there is no binding subelement of the target service with @name corresponding to binding-name, the SCA runtime MUST raise an error.

  • [ASM80002] Remotable service Interfaces MUST NOT make use of method or operation overloading.

  • [ASM80003] If a remotable service is called locally or remotely, the SCA container MUST ensure sure that no modification of input messages by the service or post-invocation modifications to return messages are seen by the caller.

  • [ASM90002] When a service or reference has multiple bindings, all noncallback bindings of the service or reference MUST have unique names, and all callback bindings of the service or reference MUST have unique names.

  • [ASM90005] For a binding.sca of a component service, the @uri attribute MUST NOT be present.

  • [CPP110001]: An SCA implementation MUST reject a composite file that does not conform to http://docs.oasis-open.org/opencsa/sca/200912/sca-interface-cpp-1.1.xsd or http://docs.oasis-open.org/opencsa/sca/200912/sca-implementation-cpp-1.1.xsd.

  • [CPP110002]: An SCA implementation MUST reject a componentType file that does not conform to http://docs.oasis-open.org/opencsa/sca/200912/sca-interface-cpp-1.1.xsd.

  • [CPP110003]: An SCA implementation MUST reject a contribution file that does not conform to http://docs.oasis-open.org/opencsa/sca/200912/sca-contribution-cpp-1.1.xsd

  • [ASM12001] For any contribution packaging it MUST be possible to present the artifacts of the packaging to SCA as a hierarchy of resources based off of a single root

  • [ASM12002] Within any contribution packaging A directory resource SHOULD exist at the root of the hierarchy named META-INF

  • [ASM12003] Within any contribution packaging a document SHOULD exist directly under the META-INF directory named sca-contribution.xml which lists the SCA Composites within the contribution that are runnable.

  • [ASM12005] Where present, artifact-related or packaging-related artifact resolution mechanisms MUST be used by the SCA runtime to resolve artifact dependencies.

  • [ASM12006] SCA requires that all runtimes MUST support the ZIP packaging format for contributions.

  • [ASM12010] Where present, non-SCA artifact resolution mechanisms MUST be used by the SCA runtime in precendence to the SCA mechanisms

  • [ASM12021] The SCA runtime MUST raise an error if an artifact cannot be resolved using these mechanisms, if present.

  • [ASM12025] The SCA runtime MUST raise an error if an artifact cannot be resolved by using artifact-related or packaging-related artifact resolution mechanisms, if present, by searching locations identified by the import statements of the contribution, if present, and by searching the contents of the contribution.

  • [ASM12027] An SCA runtime MUST reject files that do not conform to the schema declared in sca-contribution.xsd.

  • [ASM12032] Checking for errors in artifacts MUST NOT be done for artifacts in the Installed state (ie where the artifacts are simply part of installed contributions)

  • [ASM12033] Errors in artifacts MUST be detected either during the Deployment of the artifacts, or during the process of putting the artifacts into the Running state,

  • [ASM13001] An SCA runtime MUST reject a composite file that does not conform to the sca-core.xsd, sca-interface-wsdl.xsd, scaimplementation- composite.xsd and sca-binding-sca.xsd schema.

  • [ASM13002] An SCA runtime MUST reject a contribution file that does not conform to the sca-contribution.xsd schema.

  • [ASM13003] An SCA runtime MUST reject a definitions file that does not conform to the sca-definitions.xsd schema.

  • [CPP20007]: The @name attribute of a function child element of a interface.cpp MUST be unique amongst the function elements of that interface.cpp.

  • [CPP20008]: The @name attribute of a callbackFunction child element of a interface.cpp MUST be unique amongst the callbackFunction elements of that interface.cpp.

  • [CPP20009]: The name of the componentType file for a C++ implementation MUST match the class name (excluding any namespace definition) of the implementations as defined by the @class attribute of the implementation.cpp element.

  • [CPP20010]: The @name attribute of a function child element of a implementation.cpp MUST be unique amongst the function elements of that implementation.

Appendix Appendix B. OpenSLP error codes

 
  SLP_LANGUAGE_NOT_SUPPORTED       = -1,
   /*!< No DA or SA has service advertisement or attribute information in 
    * the language requested, but at least one DA or SA indicated, via the 
    * LANGUAGE_NOT_SUPPORTED error code, that it might have information for 
    * that service in another language.
    */

   SLP_PARSE_ERROR                  = -2,
   /*!< The SLP message was rejected by a remote SLP agent. The API returns 
    * this error only when no information was retrieved, and at least one SA 
    * or DA indicated a protocol error. The data supplied through the API 
    * may be malformed or a may have been damaged in transit.
    */

   SLP_INVALID_REGISTRATION         = -3,
   /*!< The API may return this error if an attempt to register a service 
    * was rejected by all DAs because of a malformed URL or attributes. SLP 
    * does not return the error if at least one DA accepted the registration.
    */

   SLP_SCOPE_NOT_SUPPORTED          = -4,
   /*!< The API returns this error if the SA has been configured with 
    * net.slp.useScopes value-list of scopes and the SA request did not 
    * specify one or more of these allowable scopes, and no others. It may 
    * be returned by a DA or SA if the scope included in a request is not 
    * supported by the DA or SA.
    */

   SLP_AUTHENTICATION_ABSENT        = -6,
   /*!< If the SLP framework supports authentication, this error arises 
    * when the UA or SA failed to send an authenticator for requests or 
    * registrations in a protected scope.
    */

   SLP_AUTHENTICATION_FAILED        = -7,
   /*!< If the SLP framework supports authentication, this error arises when 
    * a authentication on an SLP message failed.
    */

   SLP_INVALID_UPDATE               = -13,
   /*!< An update for a non-existing registration was issued, or the update 
    * includes a service type or scope different than that in the initial 
    * registration, etc.
    */

   SLP_REFRESH_REJECTED             = -15,
   /*!< The SA attempted to refresh a registration more frequently than
    * the minimum refresh interval. The SA should call the appropriate API 
    * function to obtain the minimum refresh interval to use.
    */

   SLP_NOT_IMPLEMENTED              = -17,
   /*!< If an unimplemented feature is used, this error is returned. */

   SLP_BUFFER_OVERFLOW              = -18,
   /*!< An outgoing request overflowed the maximum network MTU size. The 
    * request should be reduced in size or broken into pieces and tried 
    * again.
    */

   SLP_NETWORK_TIMED_OUT            = -19,
   /*!< When no reply can be obtained in the time specified by the configured 
    * timeout interval for a unicast request, this error is returned.
    */

   SLP_NETWORK_INIT_FAILED          = -20,
   /*!< If the network cannot initialize properly, this error is returned. */

   SLP_MEMORY_ALLOC_FAILED          = -21,
   /*!< If the API fails to allocate memory, the operation is aborted and 
    * returns this.
    */

   SLP_PARAMETER_BAD                = -22,
   /*!< If a parameter passed into an interface is bad, this error is 
    * returned.
    */

   SLP_NETWORK_ERROR                = -23,
   /*!< The failure of networking during normal operations causes this error 
    * to be returned.
    */

   SLP_INTERNAL_SYSTEM_ERROR        = -24,
   /*!< A basic failure of the API causes this error to be returned. This 
    * occurs when a system call or library fails. The operation could not 
    * recover.
    */

   SLP_HANDLE_IN_USE                = -25,
   /*!< In the C API, callback functions are not permitted to recursively 
    * call into the API on the same SLPHandle, either directly or indirectly.  
    * If an attempt is made to do so, this error is returned from the called 
    * API function.
    */

   SLP_TYPE_ERROR                   = -26
   /*!< If the API supports type checking of registrations against service 
    * type templates, this error can arise if the attributes in a 
    * registration do not match the service type template for the service.
    */
	
 

Glossary

Trentino Glossary

SCA

The Service Component Architecture Specification

SCA Contribution

A contribution is a set of artifacts ready for deployment on a Trentino Runtime. It typically contains composites and related artifacts that will be deployed on the SCA runtime. A contribution can refer to other contribution, so that installed contribution can be reused.