Introduction

Welcome to the first of a series of tutorials detailing the construction, configuration and execution of distributed Ada applications. The tutorials are intended to ease a newcomers entry to building distributed applications with Ada.

More information on DSA can be found here:

Annex E: Distributed Systems

The Distributed Systems Annex describes the facilities available for implementing distributed systems. A distributed systems is basically a program where selected parts of the program run on different processing and storage nodes. DSA in short enables you to distribute workload easily across multiple physical computers and it makes network communication completely transparent among the clients and servers.

The possibilities with DSA are nearly endless, so it is well-worth the effort to learn a bit about this marvelous technology.

Design

The hello DSA application is perhaps the simplest possible example of a DSA application.

The main application entities are:

Server:

  • exists as a single instance
  • provides a single service greet, which returns a greeting string to a Client
  • implemented as a DSA remote call interface package

Client:

  • many instances may exist
  • a Client instance will request the Server's greet message and displays it, in an infinite loop.
  • implemented as a normal Ada package

Applets:

  • Two applets exist to launch the server or a client
  • These are implemented as normal Ada main subprograms

The source code is simple enough that it may be presented herein …

Source Code

Server:

Copy the following into a file called server.ads.

package Server is
   pragma remote_call_Interface;
   function Greeting return String;
end Server;

Copy the following into a file called server.adb.

package body Server is
   function Greeting return String is
   begin
      return "Greetings, Earthling.";
   end;
end Server;

Client:

Copy the following into a file called client.ads.

package Client is
   procedure Start; 
end Client;

Copy the following into a file called client.adb.

with Server;
with ada.Text_IO;   use ada.Text_IO;
 
package body Client is
   procedure Start is
   begin
      loop
         delay 1.0;
         put_Line ("Server says: '" & Server.Greeting);
      end loop;
   end;
end Client;

Applets:

Copy the following into a file called start_server.adb.

with Client;
with Server;
procedure start_Server is
begin
   loop
      delay 0.5;
   end loop;
end;

Copy the following into a file called start_client.adb.

with Client;
procedure start_Client is
begin
   Client.start;
end;

Preparation

Of course, we need an Ada compiler and DSA implementation. A good choice might be the Gnat and Polyorb (GPL11) versions available at Libre.

Polyorb will need to be built from source via:

$ ./configure  --enable-debug  --with-appli-perso="dsa"  --with-proto-perso="giop"
$ make
$ make install

Now that our tools are installed, we can build the distributed application…

Build

To build a distributed application, po_gnatdist is used, instead of gnatmake.

Instead of producing a single executable (as gnatmake does), po_gnatdist will produce an executable for each partition involved in the distributed application. In our case, an executable for each of the Server partition and Client partition will be produced.

po_gnatdist is fed a build-time configuration file, which tells po_gnatdist which package belongs to which partition executable.

For Greetings Earthling, the following dsa.cfg is our build-time configuration for po_gnatdist.

Copy the following to a file called dsa.cfg.

configuration DSA is 
   pragma Starter (none);          
   --  Tell 'po_gnatdist' to not create any startup script or launcher (more on this in a lter tute).                                          
   --  We will launch our Server and Client partitions manually from a console. 
 
   --  Server
   server_Partition : partition := (Server);                                              
   --  Declare the Server partition and assign the 'Server' remote call interface package to this partition.
   procedure start_Server is in server_Partition;                                    
   --  Tell po_gnatdist that the 'start_Server' procedure is the the Servers 'main' subprogram or launcher. 
 
   --  Client
   client_Partition : partition;                                                                
   --  Declare the Client partition (which has no remote call interface package associated with it, so no 'initialisation' is required).
   procedure start_Client;                                                                     
   --  Declare the Clients 'main' subprogram or launcher. 
   for client_Partition'Main use start_Client;                                         
   --  Tell po_gnatdist to assign the above declared 'start_Client' procedure as the Clients 'main' subprogram or launcher.
   for client_Partition'Termination use Local_Termination;                  
   --  Tell po_Gnatdist that Clients may terminate locally (more on this later).
 
   --  Misc
   for Partition'Directory use "bin"; 
   --  Ask po_gnatdist to place the built Client and Server partition executables in the './bin' sub-folder.
end DSA;

Finally, we invoke the build with:

$ po_gnatdist dsa.cfg

This should build both the Server and Client partition executables and place them in the ./bin directory.

Trial

Now that both client and server partitions have been built, we can test them, first locally within a LAN, and then across a WAN via the internet.

Local Area Net Test

In Brief

  1. Run-time configuration: (polyorb.conf)
  2. start po_cos_naming:
  3. start Server:
  4. start Client:

Detailed

Run these commands:

$ mkdir namer
$ cd namer

Put this text into a file called polyorb.conf in the namer directory:

[iiop]
polyorb.protocols.iiop.default_port=9099

You can use any port you want, just pick one that's not being used by something else. Numbers in the range 1025 .. 65535 are valid. This number should be fine for this test. Then run this command (you should still be in the namer directory):

$ po_cos_naming

That will print out two long environment variable declarations, then sit and wait. Copy the value (but not the name) of the shorter one (the one called POLYORB_CORBA_NAME_SERVICE) and put it in place of the similar string (the corbaloc part) in the text below. Change the port number (the number after the ”:”) to the one we used above; the rest should be kept as printed by the command. Put the revised text into a file called polyorb.conf (a different one than the polyorb.conf we created above in the namer subdir; this one goes wherever you run the client and server commands from):

[dsa]
name_service=corbaloc:iiop:1.2@192.168.1.1:9099/NameService/000000024fF0000000080000000

[iiop]
polyorb.protocols.iiop.default_port=5001

Again, the port number used by the client and server (the 5001 in the fourth line) is up to you, but this value should work for this test.

Now open two more terminal windows. In one, run this command:

$ bin/server_partition

That should start the server, which should sit and wait for connections from clients. You may note that the namer window printed out a bunch of text when the server started; this is to be expected, and can be ignored.

In the second new terminal, run this command:

$ bin/client_partition

That should start the client, which should connect to the server and start printing out the server's greeting message.

Congratulations, you've gotten DSA running!

Wide Area Net Test

In Brief

  1. adjust /etc/hosts:
  2. open ports:
  3. Run-time configuration: (polyorb.conf)
  4. start po_cos_naming:
  5. start Server:
  6. start Client:

Detailed To be done


Navigation