Files
PolyORB/doc/polyorb_dg.texi
Thomas Quinot 534bd94743 Convert PolyORB UG to Sphinx
NB28-010

Subversion-branch: /trunk/polyorb
Subversion-revision: 239160
2015-05-29 12:47:39 +00:00

980 lines
32 KiB
Plaintext

@c Copyright (C) 2004-2015, Free Software Foundation, Inc.
\input texinfo @c load conversion file for TeX format
@c start of the header
@setfilename polyorb_dg.info
@settitle PolyORB Developer's Guide
@documentlanguage en
@documentencoding US-ASCII
@syncodeindex fn cp
@c end of the header
@copying
Here shall lie the licence of this document
@end copying
@titlepage
@title PolyORB Developer's Guide
@author Thomas Vergnaud
@page
@vskip 0pt plus 1filll
@insertcopying
@end titlepage
@contents
@ifnottex
@node Top
@top PolyORB Developer's Guide
@insertcopying
@end ifnottex
@menu
* About this guide::
* Introduction::
* Main packages::
* Application personalities::
* Protocol layer::
* Neutral layer::
* Services::
* Coding rules::
* GNU Free Documentation License::
@end menu
@c -------------------------------------------------------------------
@node About this guide
@unnumbered About this guide
@c -------------------------------------------------------------------
@noindent
This guide aims at giving you some information about the PolyORB
global structure, in order to help find your way though the packages.
It also gives you hints on how to build protocol or application
personalities.
@node Introduction
@chapter Introduction
@cindex Introduction
PolyORB aims at providing a uniform solution to build distributed
applications. To do so, the architecture of PolyORB allows for
providing multiple middleware behaviors, both on the application side
(e.g. CORBA, Distributed Systems Annex of Ada 95) and protocol side
(e.g. GIOP, SOAP). Those behaviors are implemented by
``personalities'', which can be viewed as interfaces between networks
or applications and the PolyORB core. Through them, PolyORB behaves as
if it were a particular middleware implementation.
Personalities mainly use or extend mechanisms that are provided by the
PolyORB core, and thus adapt them to implement specific
implementations. As the PolyORB core provides the basis of all what
personalities provide, it is called ``neutral core''.
What is very special in the PolyORB architecture, is that there can be
multiple application and protocol personalities in the same configuration.
Thus, PolyORB is said to have a ``schizophrenic architecture''.
@cindex schizophrenic architecture
The architecture of a PolyORB personalisation is made of three layers:
@itemize @bullet
@item the application personalities;
@item the neutral layer;
@item the protocol personalities.
@end itemize
Above the application personalities lie the user applications; the
protocol personalities directly rely on the network.
Actually, one can view three sublayers within the neutral layer. At
the very heart of the layer, there is the neutral core, which is
nearly a middleware implementation in itself. Above and below the
neutral inner core lie the mechanisms to operate with the
personalities.
@node Main packages
@chapter Main packages
As PolyORB is a rather big program, here is a short description of the
main packages, in order to help you find what functionality you
search. All these packages are located in @code{src/}.
@c -------------------
@section Tool packages
Those packages provide various tools and facilities, which can be used
by all other PolyORB packages.
@subsection @code{PolyORB.Calendar}
A calendar implementation that works with all tasking policies. See
@ref{calendar} for details.
@subsection @code{PolyORB.Log}
Logging facility. Provides a unified means for other units
to output debugging, diagnostics and error messages.
@subsection @code{PolyORB.Utils.Chained_Lists}
Generic chain list facility with generic iterator.
@subsection @code{PolyORB.Utils.Dynamic_Tables}, @code{PolyORB.Utils.Htables.*}
Functions to handle arrays of variable size, and hash tables.
@subsection @code{PolyORB.Utils.Simple_Flags}
Utility functions to provide binary flag sets.
@subsection @code{PolyORB.Utils.Strings.Lists}, @code{PolyORB.Utils.Strings}
Handling of dynamic string allocation and chained lists of strings.
@subsection @code{PolyORB.Sequences.*}
@{Bounded,unbounded@} variable length arrays (cf. CORBA.Sequences.)
Notionally based on Ada.Strings.Unbounded.
@subsection @code{PolyORB.Dynamic_Dict}
Efficient dictionnary of key-value pairs.
@subsection @code{PolyORB.Utils.Random}
A random number generator, which is meant to replace
Ada.Numerics.Discrete_Random.
@subsection @code{PolyORB.Fixed_Point}
A package to represent fixed point numbers.
@c --------------------------------
@section Configuration packages
Those packages support the main configuration functionalities of
PolyORB.
@subsection @code{PolyORB.Configuration}
User control of various middleware aspects is implemented
through a generic configuration framework.
At start-up, PolyORB will search for various configuration files,
containing application profiles. See 'polyorb.conf' for a detail
of PolyORB generic configuration, 'moma/*.conf' for MOMA specific
configuration files.
@subsection @code{PolyORB.Initialization}
Software modules manager for initialization of the middleware. Each
module is registered with this package, indicating its
dependencies. Initialization is performed as a topological sort of the
dependency lattice. A check is performed to control consistency of the
tree.
@subsection @code{PolyORB.Tasking.*}
Tasking runtime, support full tasking, ravenscar tasking subset and no
tasking modes. Provides advanced mutexes, mutexes, watchers, r/w locks
abstractions.
@subsection @code{PolyORB.Setup.*}
Handle the initialization of a PolyORB node.
@subsection @code{PolyORB.Parameters.*}
Facilities to read and handle configuration parameters. Among other
things, those packages are used to manage the configuration file
@code{polyorb.conf}.
@c ------------------------
@section Data manipulation packages
Those package gather all functions and definitions concerning the data
handled within the neutral layer.
@subsection @code{PolyORB.Types}
Base data types used throughout PolyORB.
@subsection @code{PolyORB.Any.*}
Neutral, self-descriptive data representation. See @ref{any types} for
details.
@c -------------------------
@section Architectural packages
Those packages do not correspond to functional parts of PolyORB: they
provide architectural components.
@subsection @code{PolyORB.Annotations}
The Annotation pattern, which allows clients of a data structure
to independently enrich it, thus decoupling data extension from
type extension.
@subsection @code{PolyORB.Components}
The Component pattern, which allows objects to exchange
synchronous messages through connections, thus decoupling
behaviour profiles from Ada typing.
@subsection @code{PolyORB.Smart_Pointers}
The smart pointers are used to reproduce a garbage collecting process.
@c -----------
@section Application layer framework and support functionalities
@subsection @code{PolyORB.Call_Back}
Interceptor for request processing completion signalling.
@subsection @code{PolyORB.Obj_Adapters}
The abstract interface of object adapters in PolyORB.
@subsection @code{PolyORB.Poa}
The base class for all Portable Object Adapter implementations (generic
hierarchical object adapters modeled after the CORBA POA.)
@subsection @code{PolyORB.Poa_Types}
Base data structures handled by PolyORB.POA.
@subsection @code{PolyORB.Poa_Policies}
Children of this unit define various policy objects that can be used
to customise the behaviour of portable object adapters.
@subsection @code{PolyORB.Servants}, @code{PolyORB.Minimal_Servants}
Base class for all application objects.
@c -----------------------------
@section Neutral Core
@subsection @code{PolyORB.Orb}
The core component: provides the global ORB activities scheduler,
as well as registries for personality components (binding object
factories, transport access points, object adapters).
@subsection @code{PolyORB.Requests}
The central data structure in PolyORB: an object representing a method
invocation request to be executed by an object in a way that is independent
of the application and protocol personalities.
@subsection @code{PolyORB.References}
Object reference management.
@subsection @code{PolyORB.References.Binding}
Client-side binding factory. Either binds directly
or creates a binding to a remote object.
@subsection @code{PolyORB.Scheduler}
Coordinates the scheduling policies for the tasks that have been
created by the ORB.
@subsection @code{PolyORB.Jobs}
A Job is anything that can keep a task busy (like a Runnable
in Java). This unit declares an abstract Job type, and a means
to maintain job queues.
@c -------------
@section Protocol layer framework and support functionalities
@subsection @code{PolyORB.Opaque.Chunk_Pools}, @code{PolyORB.Opaque}, @code{PolyORB.Buffers}
Manage memory buffers for various purposes
@subsection @code{PolyORB.Utils.Buffers}, @code{PolyORB.Utils.Text.Buffers}
Utilities for buffer access.
@subsection @code{PolyORB.Filters}
Framework for layered components that form a protocol stack. Each
filter transmits SDUs (service data units) from its lower layer to its
upper layer, and can perform some processing on the SDU and its
associated data.
The lowest layer is a polyorb.filters.sockets.socket_filter, which
does not receive SDUs from a lower layer but directly from the ORB
engine.
The uppermost layer is a Session, which does not actually transmits
SDUs to an upper layer but takes action based on received SDUs.
@subsection @code{PolyORB.Transport}
The abstraction of access points and end points in the transport
service. An access point is an entity that has an address, to which
other nodes can connect. An end point is an entity that represents an
established connection with an access point, and can be used to
exchange information.
@subsection @code{PolyORB.Transport.Sockets}
A concrete implementation of the classes defined in PolyORB.Transport,
based on TCP sockets.
@subsection @code{PolyORB.Representations}
The abstraction of a method to represent data in a form suitable for
transmission. Children of this unit are expected to derive the
PolyORB.Representations.Representation abstract type into a concrete
type implementing one representation mechanism.
@subsection @code{PolyORB.Protocols}
The abstraction of a remote invocation protocol. To be derived by
concrete personalities. A Protocol is a factory of Session. A Session
is the actual object that implements one particular
protocols. Protocols are factories of Sessions, and are used as parts
of binding object factories.
@subsection @code{PolyORB.Binding_Data}
Client-side remote binding object factories.
@c ---------
@section Socket manipulation
Those package handle low-level operations.
@subsection @code{PolyORB.Sockets.*}
Socket management. Protocol personalities are placed between those
packages and the lower part of the neutral layer.
@subsection @code{PolyORB.Asynch_Ev.*}
Asynchronous event sources objects, which can trigger asynchronous
ORB activities to react to external stimuli.
@node Application personalities
@chapter Application personalities
@noindent
Application personalities constitute the application layer, which is
the upper part of PolyORB. Application personalities act as an
interface between user applications and inner middleware (i.e. the
neutral layer, @ref{Neutral layer}).
The client part consists of forwarding the requests made by the
application to the proper neutral primitives. The server part of a
personality mainly consists of a set of servants that handle requests.
Two kinds of servants are integrated into PolyORB: ``normal servants''
and minimal servants.
@section Setting a ``normal'' servant
Servants are components (@pxref{components}) that receive requests, do
some work on them, and then may return an answer.
@subsection Creating a servant
The type @dfn{Servant} is defined in @code{PolyORB.Servants}, and is
an abstract type, which must be derived to create a concrete servant
type that will handle the requests sent to the application managed by
your personality.
Along with this type, you must write a @code{Execute_Servant} function
that will receive messages, do some work, and then return another
message. Basically, two kinds of messages are associated to servants:
@code{Execute_Request} and @code{Executed_Request}, which are defined
in @code{PolyORB.Servants.Interface}. Thus, the body of
@code{Execute_Servant} should test if the incoming message is of type
@code{Execute_Request}, and return a message of type
@code{Executed_Request}.
An @code{Execute_Request} message contains the request to handle, and
a profile, from which comes the request, in order to know who sent the
request. An @code{Executed_Request} message just contains the answer
(the type of which is also @code{Request}).
@subsection Registering a servant
Once you have created a servant, you have to register it to the
Neutral layer so that it can be receive requests from clients.
The registering of a servant involves the @acronym{POA} (Portable
Object Adapter, @pxref{object adapter}), which is concept coming from
@acronym{CORBA}.
Assuming you have created a POA called @code{The_POA} and you want to
register a servant called @code{The_Servant}, you have to type
something like this:
@example
PolyORB.POA.Basic_POA.Set_Servant
(PolyORB.POA.Basic_POA.Basic_Obj_Adapter (The_POA.all)'Access,
The_Servant'Unchecked_Access,
Error);
@end example
By doing this, you associated @code{The_Servant} to
@code{The_POA}. Now you just have to know which reference must be used
to reach @code{The_Servant}, in order to communicate it to the
clients. This is done by getting the ID @code{The_POA} assigned to
@code{The_Servant}, and then creating a corresponding reference:
@example
declare
Servant_Id : Object_Id_Access;
The_Reference : PolyORB.References.Ref;
begin
Servant_To_Id
(PolyORB.POA.Basic_POA.Basic_Obj_Adapter
(The_POA.all)'Access,
The_Servant'Unchecked_Access,
Servant_Id,
Error);
if not PolyORB.Exceptions.Found (Error) then
Create_Reference (The_ORB,
Servant_Id,
"",
The_Reference);
end if;
end;
@end example
And then you just have to convert the reference into an IOR, URI, or
whatever you wish (@pxref{references}).
@section Setting a minimal servant
@anchor{minimal servants}
Minimal servants are alternative to classical servants. As their name
suggests, they offer less flexibility than normal servants; however
they are easier to set up, as they are some sort of pre-defined
servants. Minimal servants are provided by the packages
@code{PolyORB.Minimal_Servant} and
@code{PolyORB.Minimal_Servant.Tools}.
As for normal servants, you first have to create a concrete type by
deriving type @code{Servant}. You also have to write the specification
of a procedure named @code{Invoke}, that more or less corresponds to
@code{Execute_Servant}. @code{Invoke} receives an access to the
request, reads it and then puts the response in it while
@code{Execute_Request} receives a message containing a request and
returns another message containing a request (which should be the one
which has been received, carrying the results).
Then you just have to call @code{Initiate_Servant}, which associates
your minimal servant to the object adapter (@pxref{object adapter})
set in the ORB.
Minimal servants actually provide a simple way to easily set up
servants without bothering about object adapter configuration. The
main consequence is that a minimal servant is always referenced to the
root object adapter, while using normal servants let you reference
your servant to an object adapter you created yourself and then set in
the object adapter arborescence.
@subsection Managing the arguments
When your servant receives a request, it must get all information in
order to correctly handle the request.
Method name is simply retrieved by reading the corresponding field
inside the request.
In order to retrieve the arguments, you have to call the procedure
@code{Arguments} of the package @code{PolyORB.Requests}. Indeed, the
argument list carried by the request contains both @code{in} and
@code{out} arguments; you only want to get the @code{in} ones.
@code{Arguments} is called with the request, a freshly created NV-List
containing the signature of the arguments you are expecting, and two
parameters indicating how to handle the argument list:
@code{Identification} and @code{Can_Extend}.
@code{Identification} allows for dealing with the different ways of
handling argument lists, corresponding to different middleware
paradigms. For example, in CORBA middleware, arguments are identified
by their position, while in Web middleware they are identified by
their name. So, for a Web personality, the order in which the
personality handles the parameters does not matter. Depending on how
the applications handle arguments, you can specify how the neutral
layer should consider the argument lists.
@code{Can_Extend} is meant to indicate wether @code{Arguments} can add
arguments to your list or not. This is useful for personalities that
do not know which arguments they are supposed to receive. This is the
case for a web personality: indeed, in this middleware paradigm, the
server reads all the arguments the client sends to it, and then looks
if there is anything interesting; in @acronym{CORBA}, client and
server follow an IDL contract, so all received arguments should be
expected, and there should be no extra ones.
@section Invoking a request
Invoking a request implies three mechanisms:
@enumerate
@item
create a request;
@item
send it through the ORB;
@item
receive and analyse the answer (if the personality is based on a
request/answer mechanism).
@end enumerate
All those operations are handled by the package
@code{PolyORB.Requests}.
@subsection Creating a new request
Before sending a request to anybody, the application personality has
to create a new one. This is done by calling @code{Create_Request}
located in the package @code{PolyORB.Requests}. The main parameters
are:
@itemize
@item
the neutral reference of the targeted object;
@item
the name of the operation you want to invoke
@item
a list containing all the arguments sent to the object;
@item
a list describing the signature of the data expected as return, and an
optional other for the possible exceptions;
@end itemize
See @ref{references} for information about how to get a neutral
reference to an object. The list of arguments is built using
functions associated to @code{NV-List}s @pxref{nvlists}. Note that
the argument list has to actually contain the arguments the
application wants to send, while the return and exception lists only
contain the signature of the expected data.
@subsection Sending a request through the ORB
Sending a request is very easy: you just have to call the
@code{Invoke} procedure located in package @code{PolyORB.Requests}.
Calling @code{Invoke} will pause your application, waiting for
getting the request back with an answer.
@subsection Handling the answer
When the request comes back from the server, the field @code{Result}
contains the answer to the request.
@section Object adapter
@anchor{object adapter}
The concept of Object Adapter comes from the @acronym{CORBA}
specifications. An object adapter manages the servants in order to
send incoming requests to the proper one.
Several packages gather the functions associated with the object
adapters: they are named @code{PolyORB.Obj_Adapter.*} and
@code{PolyORB.POA.*}.
Two kinds of object adapters are presently defined within PolyORB: the
Simple Object Adapter, defined in @code{PolyORB.Obj_Adapter.Simple},
and the Portable Object Adapter (POA), defined in packages
@code{PolyORB.POA.*}.xs
@subsection Simple Object Adapter
The @acronym{SOA} only allows for basic registering and unregistering
servants: servants are registered using @code{Export} and unregistered
using @code{Unexport}. Thus it fits well for basic needs; minimal
servants rely on the SOA (see @pxref{minimal servants}). An SOA can be
created and destroyed using procedures @code{Create} and
@code{Destroy}.
@subsection Portable Object Adapter
The @acronym{POA} behaves like what is specified in @acronym{CORBA}.
POA are organized as a tree, with a root POA. You can create POAs and
attach them to another one. Each POA has a name, which is used to
retrieve it in the tree. Each POA is associated with certain policies,
that drive its behaviour.
@subsubsection Basic POA
A @acronym{POA} implementation is located in
@code{PolyORB.POA.Basic_POA}. This means that you may create other
kinds of POA for special purposes.
In order to be used in place of an SOA, the basic POA offers the same
interface as SOA. It also offers the interface specified in
@acronym{CORBA}.
@subsubsection POA policies
A POA is managed following policies, that define how to manage
servants, etc. The available policies are those that are defined
in @acronym{CORBA}. They are located in @code{PolyORB.POA_Policies.*}
@node Protocol layer
@chapter Protocol personalities
Protocol personalities handle the communications with other nodes.
All files concerning a protocol personality are usually put in a
subdirectory of @code{src/}: @code{src/soap/} for the SOAP
personality, etc.
Creating a protocol personality is basically creating subpackages that
implement concrete functions from abstract ones declared in the
neutral layer.
On an architectural point of view, a protocol personality is a stack
of filters, like a stack of layers in OSI norms.
When a protocol personality receives a request, it has to create a
neutral request, as an application personality would do
(@pxref{Application personalities}), but without including the request
parameters. Indeed, as some protocols do not indicate the structure of
the arguments, the protocol personality has to wait for a description
of the arguments coming from the application personality (which is the
only one supposed to know what is expected, according to the request
name). When the argument description comes back through the neutral
layer, then the personality can extract (unmarshal) the arguments, and
send them.
@section Reference management
As PolyORB can handle several protocols, references are actually sets
of several @dfn{profiles}, one for each protocol. Moreover, a profile
must be printable according all available reference syntaxes (URI,
IOR, etc.). A profile is identified by a @dfn{tag}, which is
associated to a string prefix that characterizes the stringified
version of the profile (i.e. ``IOR:'' for IORs) and functions to get a
the profile from a string, and vice-versa.
In order to be usable, a protocol personality has to provide functions
to manage its profiles, and register them to the neutral layer. To do
so, you have to create a subpackage of @code{PolyORB.Binding_Data},
which will contain concrete implementations of the abstract procedure
and functions declared in @code{PolyORB.Binding_Data}. The functions
provided by this package will be called by the neutral layer in order
to make conversion between profiles and printable strings.
To specify the functions that deal with references, the package must
call the @code{Register} procedures located in packages
@code{PolyORB.References.*}, giving them the profile tag, the
stringifying and destringifying functions, etc. The call to those
procedures must be handled by the PolyORB Initialization facility. To
do so, you simple have to create a procedure that will contain all the
calls to the registering procedures, and specify that this procedure
should be called when the module is initialized by PolyORB. So you
should write something like:
@example
procedure body Initialize is
begin
-- calling the registering procedures
end Initialize;
begin
Register_Module
(Module_Info'
(Name => +"binding_data.my_proto_perso",
Conflicts => Empty,
Depends => +"sockets",
Provides => +"binding_factories",
Implicit => False,
Init => Initialize'Access));
end PolyORB.Binding_Data.My_Proto_Perso;
@end example
@section Architecture of a protocol personality
As said before, a protocol personality is mainly a stack of filters
exchanging information. The filter stack relies on an access point.
An access point is associated to a socket (@code{PolyORB.Socket},
@code{PolyORB.Transport.*}). PolyORB allows to create TCP-related
access points (@code{PolyORB.Utils.TCP_Access_Points}) or UDP-related
access points (@code{PolyORB.Utils.UDP_Access_Points}).
The filter stack is built using @code{Chain_Factories} located in
@code{PolyORB.Filters}.
The access points is then registered to the ORB, using
@code{Register_Access_Point}.
@section Protocol functionalities
A protocol personality provides functionalities to perform various
operations concerning the requests. To do so, you have to create a
subpackage @code{PolyORB.Protocols.My_Proto_Perso}, which contains
concrete implementations of the abstract procedures declared in
@code{PolyORB.Protocols}.
@node Neutral layer
@chapter Neutral layer
@noindent
The Neutral Layer is actually the inner middleware in itself. It
offers several services and mechanisms to personalities.
@section References
@anchor{references}
@cindex references
@noindent
@dfn{References} are used to identify an object, a resource, or
whatever you may call it in the middleware paradigm you plan to
implement.
References generation and conversions are handled by the package
@code{PolyORB.References} and its subpackages.
Given a string representing an IOR, URI, Corbaloc, etc.@:,
@code{PolyORB.References} provides the procedure
@code{String_To_Object} that converts the string into a reference.
The symmetric operation is implemented in subpackages
@code{PolyORB.References.IOR}, @code{PolyORB.References.URI},
etc@. Each subpackage provides a function called
@code{Object_To_String} that returns a representation of the reference
using IOR, URI, etc@.
@section Components
@anchor{components}
@section Any types and associates
@anchor{any types}
Data that are exchanged between client and server are transported in
what are called @dfn{Any types}. Any types can carry various data
types: integer, string, etc.@: An Any type associates raw data to a
@dfn{TypeCode}, which indicates the nature of the
data.
@subsection Any types
All usefull functions dealing with Any types are located in package
@code{PolyORB.Any}. @code{PolyORB.Any} provides functions to compare
Any types, get their TypeCode (in order to know what kind of data
extract from them), build them and extract data from them, etc.@:
TypeCode are predefined for simple data types: Long, String, etc.@: So
@code{PolyORB.Any} provides @code{To_Any} functions to build Any types
from simple data types (integer, string, etc.), and symmetrically
provides @code{From_Any} functions to extract data from an Any type.
Complex types are a little more tricky: indeed, you have to create an
appropriate @dfn{TypeCode}, then create an Any type with this
TypeCode, and then store your data into it. The specification of the
package describes the right way for creating such complex Any types.
Here is a small example (adapted from @code{SOAP.Types} in the Web
personality). Let's suppose we want to create an array of long
integers. We first have to declare a new TypeCode, using the
stereotype @code{TC_Array}.
@example
Ar_Type : PolyORB.Any.TypeCode.Object
:= PolyORB.Any.TypeCode.TC_Array;
@end example
Then, as indicated in the specification, we have to store the size of
the array and then the type of the data we want to store.
@example
PolyORB.Any.TypeCode.Add_Parameter
(Ar_Type,
PolyORB.Any.To_Any (PolyORB.Types.Unsigned_Long
(Size_Of_The_Array_To_Store)));
PolyORB.Any.TypeCode.Add_Parameter
(Ar_Type,
To_Any (PolyORB.Any.TypeCode.TC_Long));
@end example
We then have a proper TypeCode; we have to create an Any with this TypeCode:
@example
Ar : PolyORB.Any.Any :=
PolyORB.Any.Get_Empty_Any_Aggregate (Ar_Type);
@end example
Finally we store the array into the Any:
@example
for K in The_Array'Range loop
PolyORB.Any.Add_Aggregate_Element
(Ar, To_Any (The_Array (K)));
end loop;
@end example
In order to retrieve data from an Any, we first get the TypeCode of
the Any:
@example
Kind_Of_Any : constant PolyORB.Any.TCKind
:= PolyORB.Any.TypeCode.Kind
(PolyORB.Any.Get_Unwound_Type (The_Any));
@end example
Considering this is an array, we then have to extract its size and the
type of data:
@example
if Kind_Of_Any = Tk_Array then
declare
use PolyORB.Types;
Number_Of_Elements : constant Unsigned_Long
:= Unsigned_Long (PolyORB.Any.TypeCode.Length
(PolyORB.Any.Get_Type (The_Any)));
Element_Type : constant PolyORB.Any.TypeCode.Object
:= PolyORB.Any.TypeCode.Content_Type
(PolyORB.Any.Get_Type (Item));
The_Array : array (1 .. Integer (Number_Of_Elements))
of Element_Type;
@end example
Finally, we retrieve all element one by one:
@example
begin
for Index in 1 .. Number_Of_Elements loop
The_Array (Index) := From_Any
(PolyORB.Any.Get_Aggregate_Element
(The_Any, Element_Type,
PolyORB.Types.Unsigned_Long (Index - 1)));
end loop;
end;
end if;
@end example
@subsection Named Values
@anchor{named values}
@dfn{Named Values} are data structure associating an Any type and a
string representing the data name. Named Values transport data along
with a type (provided by the Any type) and a name (stored in the
string), thus allowing to fully identify data.
Functions to handle Named Values are provided by @code{PolyORB.Any}.
@subsection NV-Lists
@anchor{nvlists}
@cindex nv-lists
@dfn{NV-List} stands for ``Named Value List''. This directly comes
from the @acronym{CORBA} specifications. All data transferred across
layers are put in NV-Lists.
The package @code{PolyORB.Any.NVLists} provides primitives to handle
NV-Lists. Before using a NV-List, you must create it using
@code{Create}; then you can add NamedValues or Any types using
@code{Add_Item} (in fact, adding an Any type will result in building a
Named Value an adding it to the NV-List). When you have finished using
the NV-List, you destroy it using @code{Free}.
@node Services
@chapter Services
PolyORB contains several packages offering services to developer.
@section Exceptions
@anchor{exceptions}
PolyORB introduces its own system of exceptions, which should be used
instead of Ada exceptions. PolyORB exceptions are defined in
@code{PolyORB.Exceptions}. they basically consist of an out parameter
passed to procedures. This may appear obsolete compared to Ada
mechanism; the main advantage of this approach is that it increases
performances compared to Ada exceptions.
@section Logging facility
The package @code{PolyORB.Log} provides a facility to display messages
on screen, typically for debugging purposes. You can use this package
this way:
@example
with PolyORB.Log;
package body MyPackage is
use PolyORB.Log;
package L is new PolyORB.Log.Facility_Log ("my.facility");
procedure O (Message : in Standard.String; Level : Log_Level := Debug)
renames L.Output;
...
pragma Debug (O ("hello there!"));
@end example
The parameter @code{Level} indicates the default logging level,
allowing for a hierarchy in messages. Usually this is set to
@code{Debug}. See @code{polyorb-log.ads} for the list of possible log
levels.
When the application is launched, the logging facility looks for a
file named @code{polyorb.conf} in the current directory. This file
should contain lines indicating from which log level messages should
be logged. The reference @code{polyorb.conf} file is located in the
src/ subdirectory. So you just have to copy it into your execution
directory and add the required lines. In our example, you should add
@example
my.facility=debug
@end example
indicating that all messages of higher importance than ``debug''
should be displayed. If you did not add a line for your logging
facility, then ``notice'' is used as a default value.
@section Calendar
@anchor{calendar}
Due to PolyORB configurability towards tasking policies, there are
restrictions regarding which package to use to get the time. Thus,
Ravenscar compliant applications cannot use @code{Ada.Calendar}. In
the other hand, systematically relying on @code{Ada.Real_Time} to get
the time may uselessly use the memory. You should use the package
@code{PolyORB.Calendar}, which provides the primitives of
@code{Ada.Calendar}, and the implementation of which depends on the
tasking policy.
@node Coding rules
@chapter Coding rules
You should follow a few coding rules, in order to preserve harmony in
the code. Basically, you must follow the GNAT coding style, and a few
others that are mentioned in a file named @code{CODING_GUIDELINES},
located in the @code{doc/} subdirectory.
@include gfdl.texi
@bye