HomeForumSourceResearchGuide
<< back to guide home

Dana's standard release package includes a simple meta-composer called esher which is designed to help interactively demonstrate the mechanics of dynamic system composition and runtime adaptation in an interactive way. Note that an automated meta-composer like PAL is normally used in serious systems, but esher offers a "manually-driven" insight into what a system like PAL does and can help understand how you might build your own automated meta-composer.

As an example system here we'll use TCP/IP and perform runtime adaptation at the server. The architecture of our system will look like this:

Source code to download

First we'll explain the code we'll be using to create the above system. You can download the entire example project in a single zip file here, or follow the below steps.

Create a new directory called "esher_example" and inside it create a directory called "resources". Inside "resources" create a further directory called "data". Download the following two files into the resources/data/ directory.

Source.dn
interface Source{
    transfer int number
    int getNextNumber()
    }
SourceReply.dn
data SourceReply{
    int4 number
    }

During compilation this interface and data type can be accessed using data.Source and data.SourceReply respectively.

The rest of the source files will go directly into the esher_example directory that you created. Download each of the following files to that directory:

Server.dn
uses data.SourceReply
 
component provides App requires net.TCPServerSocket, net.TCPSocket, data.Source source {
    
    void handleStream(TCPSocket client)
        {
        SourceReply reply = new SourceReply()
        reply.number = source.getNextNumber()
        client.send(dana.getByteArrayOf(reply))
        client.disconnect()
        }
    
    int App:main(AppParam params[])
        {
        TCPServerSocket master = new TCPServerSocket()
        master.bind(TCPServerSocket.ANY_ADDRESS, 2014)
        
        while (true)
            {
            TCPSocket client = new TCPSocket()
            if (client.accept(master))
                handleStream(client)
            }
        
        return 0
        }
    }
Client.dn
uses data.SourceReply
 
component provides App requires io.Output out, data.IntUtil iu, net.TCPSocket, time.Timer timer {
    
    int App:main(AppParam params[])
        {
        TCPSocket client = new TCPSocket()
        
        while (true)
            {
            if (client.connect("127.0.0.1", 2014))
                {
                SourceReply reply = new SourceReply()
                
                dana.serial(reply) =[] client.recv(dana.serial(reply).arrayLength)
 
                out.println(iu.intToString(reply.number))
                }
            
            timer.sleep(2000)
            }
            
        return 0
        }
    }
SourceA.dn
component provides data.Source{
    
    int Source:getNextNumber()
        {
        number ++
        return number
        }
    }
SourceB.dn
component provides data.Source{
    
    int Source:getNextNumber()
        {
        number += 2
        return number
        }
    }

And place the following configuration fragments into the same adaptation directory:

server.txt
App=Server.o
net.TCPServerSocket->TCP
net.TCPSocket->TCP
data.Source->Source
client.txt
App=Client.o
time.Timer->Timer
net.TCPSocket->TCP
tcp.txt
TCP=net/TCP.o
timer.txt
Timer = time/Timer.o
sourcea.txt
Source=SourceA.o
sourceb.txt
Source=SourceB.o

Compiling, running and adapting the system

Next, open a command prompt in your esher_example directory and compile each of the above components as follows:

dnc Server.dn
dnc Client.dn
dnc SourceA.dn
dnc SourceB.dn

Now open a second command prompt in the same directory which we'll use for the client side of the system.

In both command prompts issue the command:

dana esher

In the first command prompt use esher's commands to add in the components that we need for the server side of the system by issuing the following sequence:

add server.txt
add tcp.txt
add sourcea.txt

In the second command prompt add in the components that we need for the client side of the system with the following sequence of commands:

add client.txt
add tcp.txt
add timer.txt

The second command prompt should now start printing out one number every two seconds. We'll now perform some runtime evolution at the server side.

Back in the first command prompt we start by adding in the alternative "Source" implementation:

add sourceb.txt

Now we have two different implementations of the same provided interface type present in the system at the same time. If we use the pa command we'll see a report like this:

[0]: App (Server.o)
    TCPServerSocket -> TCP
    TCPSocket -> TCP
    Source -> Source
[1]: TCP (net\TCP.o)
[2]: Source (SourceA.o)
[3]: Source (SourceB.o)

We can use esher's tra command to switch between two implementations. Keep an eye on the client output in the second command prompt, and while you do so in the first command prompt use the command:

tra App data.Source 3

This tells esher to switch the App component's dependency called Source to now be resolved against component index number 3 (i.e. SourceB.o). When you press enter the transformation takes place immediately and you'll see in the client output that the numbers start incrementing by 2 instead of by 1. Importantly you'll notice that no number in the sequence is missed when the transition is made. You can switch back to the original implementation again with the command:

tra App data.Source 2

Again you'll see the change immediately in the client-side which will return to increments of 1, again without missing a number in the sequence. You can further modify the system by using esher's rem command to remove whichever of the Source variants is not currently in use, for example rem 2 if you're not currently using SourceA.o. Add it back in with add sourcea.txt as normal.

Dana's standard set of examples includes esher configurations for several GUI-based programs (in the components/examples folder). You can run these for example using the command dana esher conf_simple_ui.txt after which you can experiment with different adaptations (e.g. using the configuration fragments in the “conf” directory) of the running program.