Table of Contents Previous Chapter 10 How to Use the SDT Public Interface

10 How to Use the SDT Public Interface

This chapter contains a number of examples of how the use the features provided by the SDT Public Interface. For a reference to the topics that are exemplified in this chapter, see chapter 43, The SDT Public Interface.

Introduction

The first example shows a simple application, the Service Encapsulator, by which it is possible to request SDT services from the Operating Systems command line. The example shows how to use the PostMaster interface.

The second example uses the Service Encapsulator and shows the usage of some SDT Services.

The third example exemplifies how to integrate an SDT simulator and a separate user interface. How to design such a user interface, especially by using TeleUSE (R) , is described in a detailed example.

It is assumed that the reader has experience of creating and running SDT simulators. Parts dealing with graphical user interfaces assume experience of using TeleUSE (R) .

The Service Encapsulator

Introduction to the Service Encapsulator

This section shows an application, the Service Encapsulator, implementing a command line service request encapsulation. That is SDT services as made available by The SDT Public Interface, could be obtained from the command line.

The purpose of this example is to show

The application is general in the sense that does not require SDT to be running (only the PostMaster is required to be running), but in this context it exemplifies a number of SDT services,

From the outside world the application behaves like a tool providing remote procedure call functionality. That is, when the service is requested, the application synchronously waits for the service reply, before returning (the application exits).

The example is found in the SDT distribution in the sub directory examples/services.

Design

In this section is a few important aspects in the design and implementation of the Service Encapsulator given. The source file is named ServiceEncapsulator.c.

The tool connects to the PostMaster by issuing:

SPInit(SET_EXTERN, argv[0], spMList)
The first parameter gives the type of application. In this case SET_EXTERN is used. This application type is a predefined tool type for external applications connecting to SDT. The variable spMList gives the possibility to convert between textual (symbolic) values and integers.

If SPInit succeeds, SPinit broadcasts a SESTARTNOTIFY, indicating to all other tools in the environment that an additional tool is connected.

   if ((tool=atoi(argv[1])) == 0 )
     tool = SP(argv[1]);
If the parameter <tool> was given textually, the function SP converts it to the corresponding integer value. If a mapping cannot be found, -1 is returned and we exit the application.

if ((sendEvent=atoi(argv[2])) == 0 )
   if ((sendEvent = SP(argv[2])) == -1 ) {
      printf{"No such service\n");
      exit(1);
   }
The macro SP_ISREQUEST returns true if the issued message is of service request format.

if ( ! SP_ISREQUEST(sendEvent) ) {
   printf("Not a service\n");
   exit(1);
}
The tool provides a simple support for the create attribute and the update attribute services. These services are special since they make use of binary data. Even ASCII based data must be converted to binary. The conversion done in the tool only works for simple examples. Real application using these services, should be programmed in C.

We know that the ninth parameter contains the data part, which is to be converted. Its' length is calculated and appended to the string to be sent followed by a terminating ASCII 0. Then immediately following the terminating ASCII 0 the characters in data is put using memcpy.

sprintf(s, "%d", strlen( argv[9]) );
strcat(p, s);
memcpy((char *)p+strlen(p)+1, argv[9], 
        strlen(argv[9]));
status = SPSendToTool(tool, sendEvent, p, 
                      strlen(p)+1+strlen(argv[9]));
A normal service request is issued by:

for (i=3; i<argc; i++) {
   strcat(p, argv[i]); 
   strcat(p , " ");
}
status=SPSendToTool(tool, sendEvent, p, strlen(p)+1;
The last parameter tells the length of the parameter provided by argv[3] and must be extended by 1 to include the terminating \0 character.

Now the service request message is sent to the PostMaster which forwards it to the server application. If not busy the Service application starts to process the service request and when finished it replies with a service reply message to the issues. However, during the processing other messages can be sent or broadcasted to the Service Encapsulator (the service issuer). Therefor we must enter a loop where we stay until the reply message is received. Other kind of messages are dropped.

do {
   if (( status=SPRead(SPWAITFOREVER, &pid,
         &replyEvent,(void*)&replyMessage, &len))!=0 )
      OnError("Error reading from postmaster: ");
} while ( ! SP_MATCHREPLY(sendEvent, replyEvent) );
The function SPRead reads a message form the PostMaster. The first parameter, the timeout, could be set to wait indefinitely until a message arrives, using the value SPWAITFOREVER.

This simple application has a drawback, that if something unexpectedly happen to the server, it might be that no service reply will be sent which means that we block in SPRead forever. The behavior could be enhanced by setting a timeout, and when the timeout expires, check the state of the server (Use the PostMaster service Get Tool Pid,).

If the service readattribute was issued, special care must be taken to handle the answer, since it contains binary data. The length of the data part ends the replyMessage. The end is indicated by an ASCII 0. The data part immediately follows the ASCII 0 character and might contain non-ASCII characters. Our printout assumes ASCII data.

if ( sendEvent == SEREADATTRIBUTE ) {
   printf("%s", replyMessage+1);
   printf("%s\n", replyMessage+ strlen(replyMessage)   
          +1);
}
The macro SP_MATCHREPLY, compares the issued service request message and the reply message and returns true if the correct received message was the correct service reply message.

free (replyMessage);
replyMessage was dynamically allocated using malloc in SPRead, so it must be freed.

Before terminating the application notify all other applications in the environment that it is going to break its' connection to the PostMaster

SPBroadcast(SESTOPNOTIFY, NULL, 0);
Finally we exit calling the function.

SPExit ();

Generating the Application

To generate the application do the following:

  1. Change the current directory to the sub directory containing the example
cd $sdtrelease/examples/services
  1. Set the environment variable sdtdir to point to the right directory. This is implementation dependent.
setenv sdtdir <platform>sdtdir
  1. Generate the application.
make

Invocation

The programs takes the following parameters.

ServiceEncapsulator <tool> <service> <parameters>*
where

<tool>
is the tool that should perform the service, and

<service>
is the service itself.

<parameters>
If the service takes parameters, these should be provided as additional parameters.

The parameters <tool> and <service> could either be given as their identifying integer number or textually. See file sdt.h for definitions. The variable spMList in this file provides list of textual mappings.

Using SDT Services

Introduction

This section exemplifies the usage of some SDT services. The examples take advantage of the Service Encapsulator described in the previous section.

In these examples, we only use textual values of the parameters <tool> and <service>. Available textual values is found in the spMList variable in sdt.h.

In the examples below, the Service Encapsulator is executed from a csh shell. If another shell is used, the examples below might need to be modified in order to supply the parameters correctly. Take care how to supply the quoted strings.

Load External Signal Definitions into the Information Server

For this service to be available, the Information Server must be started, this could be done by either starting the Type Viewer from the Organizer, by requesting Signal Dictionary support in the SDL Editor or by using the Start service. For a complete service description, See "Start Tool" on page 2522 in chapter 43, The SDT Public Interface.

Requesting the service. It is assumed that a file a.pr is to be loaded. Note that the file to be loaded must be specified with a full directory path.

ServiceEncapsulator info loaddefinition /usr/ab/a.pr
If the Information Server is started, the following reply message is returned:

Reply status is OK
If the Information Server is not started, we get the following reply message.

Error sending to postmaster:  server not connected to 
postmaster

Obtain Source (SDT GR Reference)

Returns a complete SDT reference of each of the selected symbols in the specified editor.

ServiceEncapsulator sdle obtainsource
If the editor was already started and there was a selection the reply message might look like:

Reply status is OK
 1 "#SDTREF(SDL,/usr/sdt-inst/sdt3/examples/simula
tor-integration/sunos4/demon.spr(1),125(30, 70))"
Note that the reference returns a complete file path of the diagram file in which the selection was made.

If the editor did not contain any selection the reply becomes:

Reply status is OK
0
For a complete description of the service, see "Obtain GR Reference" on page 2534 in chapter 43, The SDT Public Interface.

Show Source

Selects the object given by the parameters in an editor. The editor is started if necessary as a side effect. A system must however be opened in the Organizer containing the specified reference.

To test this service we could now deselect all selections in the SDL editor and use the reference extracted by obtainsource to select this symbol again. Note how the SDT reference is quoted to pass it from the shell into the tool.

ServiceEncapsulator organizer showsource \
  """#SDTREF(SDL,/usr/sdt-inst/examples/simulator- \
  integration/sunos4/demon.spr(1),125(30,70))"""
If the reference is found the following message is replied:

Reply status is OK
For a complete description of the service, see "Show SDT Source" on page 2529 in chapter 43, The SDT Public Interface.

For a complete description of how to specify a SDT reference, see "Syntax" on page 2476 in chapter 41, References in SDT-3.

Dynamic Menus

The following example shows how a dynamic menu is created and how a number of menu items are inserted in the dynamic menu. The script dyn-menu in the example directory performs the example below.

For a complete description of the services, see "Add Menu" on page 2547, "Delete Menu" on page 2548, "Clear Menu" on page 2548 and "Add Item to Menu" on page 2549 in chapter 43, The SDT Public Interface.

Add a new menu to the SDL editor:

ServiceEncapsulator sdle menuadd \"dyn-menu\"
Reply:

Reply status is OK
Add a menu item which executes the OS command ls after a confirmation from the user:

ServiceEncapsulator sdle menuadditem  \
\"dyn-menu\" \"ls\" 0 \
\"Perform OS command ls\"  0 0 0 \
\"OK to perform ls!\" 1 1 \"ls\"
Reply:

Reply status is OK
Then a menu item is added displaying the SDT reference of the selected symbol on standard output.

ServiceEncapsulator sdle menuadditem  \
\"dyn-menu\" \"SDT-ref\" 1 \
\"export SDT ref\"  0 0 1 \
\"\" 1 1 \"echo \'%g\'\"
Reply:

Reply status is OK
Note that only dimmed if more than one item is selected. Normally a selected symbols includes a selection of in-going and out-going flowlines. These flowlines must be de-selected in order to get the SDT reference of the symbol

Finally display the file containing the selected symbol on standard output.

ServiceEncapsulator sdle menuadditem  \
\"dyn-menu\" \"filename\" 0 \
\"export filename\"  0 0 1 \
\"\" 1 1 \"ls -ls %a\"
Reply:

Reply status is OK

Extended Object Data Attributes

SDT3 allows external attributes to be added to SDT objects. These extensions are persistent. That is, they are stored in the normal SDT diagram files and could be used at subsequent sessions. This example gives a brief introduction to such extended attributes.

An description of extended attributes are found in "Extended Data Attribute" on page 2554 in chapter 43, The SDT Public Interface. Extended attributes are handled as binary data by SDT. As such, their services are preferably accessed via C program interface, in which binary data is easily handled.

However, in this example extended attribute services are accessed via the Service Encapsulator, which works for simple examples.

The example assumes one selection in an SDL editor. This reference is saved in a shell variable

set sel=`ServiceEncapsulator sdle obtainsource`
If we have exactly one selection, we set the extended attribute. Parameter 5 in sel will tell us the number of selections. Parameter 6 in sel will give us the selection.

ServiceEncapsulator sdle createattribute 0 0 $ref 0 \ 
  \"myComment\" \"\" MyData
Note that no length of data (MyData) is provided. The Service Encapsulator recognizes the service createattribute and calculates the length of data.

We get the reply:

Reply status is OK
Now we extract the extended attribute on the selection.

ServiceEncapsulator sdle readattribute 0 0 $ref
Which replies:

Reply status is OK
0 "myComment" "" 6MyData
Note that data immediately follows its' length without any spaces. In the reply message, there is a ASCII 0 character after the length, proceeding the data part.

Then we update the attribute by;

ServiceEncapsulator sdle updateattribute 0 0 $ref 0 
\"newComment\" \"\" NewData
Reply:

Reply status is OK
The Service Encapsulator also recognizes the update attribute service and calculates the length of data.

Finally we read the extended attribute and should receive the updated value.

ServiceEncapsulator sdle readattribute 0 0 $ref
Which replies:

Reply status is OK
0 "NewComment" "" 7NewData
The script extended-attributes performs the above described actions.

Integrating Applications with SDT Simulators

An example of utilizing the functionality of the PostMaster is to connect a simulator generated by SDT to another application, typically a user interface (UI). The next section, "Example of Use" on page 502, presents a detailed description of such an example. This section concentrates on overall design issues and serves as an introduction to that example.

The communication between an SDT simulator and another application is handled by the PostMaster, and can be seen as occurring on two levels:

These two levels of communication are described further below.

Transferring SDL Signals

A simulator communicates with the world outside by sending and receiving SDL signals to/from its environment. For another application to communicate with the simulator, it must also be able to interpret those SDL signals, and to send and receive them. This includes mapping the information contained in the SDL signal (name and parameters) to components and actions in the UI, e.g. pushing a button or changing the contents of an output field.

To ensure successful communication with an SDT simulator, the SDL signal interface to the environment should be designed with regard to the connected applications. Decisions made when designing a UI can influence the design of the simulator interface, and vice versa. It is important to have a clearly defined signal interface to the applications that will communicate with the simulator.

Transferring PostMaster Messages

The PostMaster communicates with different tools by sending messages of a defined format. The SDL signals must therefore be transformed to PostMaster messages before they can be transferred between the tools. A few predefined PostMaster messages are available for the purpose of handling SDL signals.

Each tool designed to communicate by using SDL signals must have an interface to the PostMaster that handles the transformation to and from an appropriate message.

In the case of an SDT simulator, this interface is generated automatically by SDT. To invoke the transformation, so that SDL signals to and from the environment are transferred using the PostMaster, the monitor command StartSDTEnv is to be used.

For other tools, the interface to the PostMaster must be implemented separately. The interface must use functions described later in this appendix to connect to the PostMaster, and to send and receive PostMaster messages containing SDL signals. This includes packing the information contained in the SDL signal (name and parameters) so that it can be sent using a PostMaster message, and unpacking the same information of a received message. See "Input and Output of Data Types" on page 1792 in chapter 32, The Simulator for more information on suitable data formats.

Example of Use

This section describes an example of how to connect a user interface (UI) to an existing SDT simulator. The simulated system used in the example is the well-known Demon game, described on "The Demon Game" on page 50 in chapter 3, Tutorial: A First Example. All necessary code for the example is provided with the SDT distribution.

The DemonGame simulator is connected through the PostMaster to a control program, consisting of two parts; an interface to the PostMaster and a user interface (see Figure 190).

The PostMaster interface establishes a connection to the PostMaster and communicates with the DemonGame simulator. Messages are sent via the PostMaster to the simulator where they are seen as SDL signals coming from the environment. Correspondingly, SDL signals to the environment are sent via the PostMaster as messages back to the PostMaster interface.

The UI facilitates sending and receiving of the SDL signals sent to and from the environment in the Demon game. Both a command-based UI (written in C) and a graphical UI (X Windows/Motif based, developed with TeleUSE) are implemented. The UI must be able to forward the SDL signals Newgame, Endgame, Probe and Result, and to present the SDL signals Win, Lose and Score.

Figure 190 : System parts and their communication. 
-----
(fig)  
       
-----
-------------------------------------------------------------------
Note:                                                                
The simulator and the control program have the same communica        
tion interface to the PostMaster. The simulator's interface to the   
PostMaster is generated automatically by SDT.                        
-------------------------------------------------------------------
Some general rules on how to design the code of a PostMaster client can be found in "Designing PostMaster Clients by Using TeleUSE" on page 511.

All C functions, C preprocessor symbols and PostMaster messages used in this example are described in "PostMaster Reference" on page 2484 in chapter 42, The SDT PostMaster.

The PostMaster Interface

All communication with the DemonGame simulator is handled by the interface to the PostMaster, a C program called env.c. This program contains the functions Init, Send_to_PM, Receive and Exit_PM, all of which must be called by the UI. Please note that the error handling in this program is very simple and does not comply with the design recommendations mentioned above.

Functions in env.c

Command-based User Interface

The command-based UI prompts for and recognizes the commands "Newgame", "Endgame", "Probe", and "Result", corresponding to the SDL signals. When any of the SDL signals Score, Win or Lose are received, this information is printed. The command "Exit" exits the program.

The C program for the command-based UI is called command.c. It contains the functions:

Functions in command.c

Graphical User Interface

The graphical UI is implemented under X Windows/Motif by using TeleUSE (R) (see Figure 191 on page 506). The four buttons corresponds to the SDL signals, and the result and score is displayed. The File menu contains the menu item Exit, which exits the application. The Help menu contains the menu item On Window, which gives short help on how to use the interface.

------------------------------------------------------------------
Note:                                                               
The version of TeleUSE supported in this example is v2.0.5. You     
may have to change the code if another version of TeleUSE is used.  
------------------------------------------------------------------
A button is only sensitive when it is meaningful to send the SDL signal. The score field is cleared whenever Probe is pushed.

Figure 191 : Graphical UI. 
-----
(fig)  
       
-----
The code for the graphical UI consists of the following:

Rules and D Events in demongame.d

INITIALLY calls Init in the PostMaster interface, and creates the widget hierarchy on the screen.

Exit is sent by the menu item Exit. It calls Exit_PM in the PostMaster interface, and exits the UI and the application.

HelpWindow is sent by the menu item On Window, and HelpOK is sent by the OK button in the help window. They manage/unmanage the help window.

Clear is sent by the INITIALLY, Newgame and Probe rules. It clears the result and score fields.

Newgame, Endgame, Probe and Result are sent by the respective buttons. They send the corresponding SDL signal by calling Send_To_PM in the PostMaster interface.
Newgame and Endgame also changes the sensitivity of the buttons.

Win, Lose and Score are sent by Send_To_UI in the UI. They update the result and score fields.

Functions in teleuse.c

Appl_Receive simply calls Receive in the PostMaster interface.

Init_UI registers the PostMaster message port as a source of events for the X Intrinsics, and sets Appl_Receive as the callback procedure to call.

Exit_UI calls Send_To_UI to send the D event Exit.

Send_To_UI sends the D event corresponding to the received signal.

Communication Diagrams

The figures below show how the different functions and other parts in the DemonGame UI communicate with each other.

Figure 192 : Communication diagram (GUI-based). 
-----
(fig)  
       
-----
Figure 193 : Communication diagram (command-based). 
-----
(fig)  
       
-----

Running the Example

To be able to build and execute the example program, the software provided on the distribution media must first be properly installed.

Building the Tools

This section describes how to build the tools that will communicate via the PostMaster, i.e. the DemonGame simulator and the UI to the simulator.

The tools are provided in source code form and in binary form for the architecture on which you have purchased SDT.

The DemonGame Simulator

In the original implementation of DemonGame provided with the SDT distribution (in the examples/demongame directory), a design error has deliberately been introduced into the game definition. See "Dynamic Errors" on page 141 in chapter 3, Tutorial: A First Example for more information.

For the example program to execute correctly, this error must be corrected. New diagrams for the block GameBlock (gameblock.sbk) and the process Main (main.spr) are therefore provided, and are to be used to generate a new simulator. You can find the necessary files in the directory named examples/simulator-integration.

  1. Either replace the above diagrams in the original DemonGame implementation, or copy the DemonGame diagrams to a new directory.
  2. Re-generate the simulator from the SDT Organizer in the usual way, and check that you now have a new .sct file.

The Command-based UI

  1. Change to the directory containing the files env.c, command.c, and makefile.
  2. Build the application with the UNIX make command. An executable named command is now created.

The Graphical UI

The Graphical UI can only be built if you have TeleUSE v2.0.5 installed.

  1. Change to the directory containing the files env.c, teleuse.c, demongame.pcd, demongame.d, demongame.aim and uxb.conf.
  2. Build the application with uxb. An executable named game is now created.

Executing a Session

This section describes how to start the communicating tools and initiate a session.

  1. Make sure you have SDT running, so that an instance of the PostMaster is started.
  2. Start the newly generated DemonGame simulator from the Organizer.
  3. Give the following commands to the simulator, preferably by including the provided command file init.sim.
    Start-SDT-Env
    Start handling of the SDL environment. See "StartSDTEnv" on page 1823 in chapter 32, The Simulator.
    Set-Trace 0
    Restrict trace output to show only signals sent to and from the SDL environment.
    Go
    Start executing the simulation.
  4. Start the command-based tool (command) or the GUI-based tool (game) from the UNIX prompt.
  5. Send SDL signals from the UI by entering the signal name or pushing the corresponding button. (See the description earlier in this section.) Note the trace output in the simulator and the output in the UI.
  6. Exit by entering "exit" or using the File menu.

Designing PostMaster Clients by Using TeleUSE

An application with a graphical UI generated with TeleUSE can be designed to communicate with an SDT simulator or other applications connected to the PostMaster. This section describes how to design the application interface to the PostMaster. As always when using TeleUSE, the overall goal should be to isolate the code handling the user interaction from the rest of the application code, so that they can be developed and maintained separately.

All communication with the PostMaster should be made through C functions which in turn call the PostMaster functions. You should implement separate functions for initializing and exiting the connection to the PostMaster, and for sending and receiving PostMaster messages. These C functions should then be called from appropriate places in the UI, either as widget callbacks or, preferably, from the D code.

Errors in the PostMaster communication are detected in the C functions, but handling of user notification should be made in the UI. This is preferably accomplished by sending a D event to the dialog by calling TeleUSE runtime functions. The D event could carry information such as an error message and the PostMaster error code, which is then appropriately displayed, for instance in a popup dialog.

The initialization function should call SPInit. The exit function should broadcast the message SESTOPNOTIFY and call SPExit.

Sending messages is quite straightforward, but receiving messages needs some special attention. To be able to listen to the PostMaster message port for incoming messages, the port must be registered as a source of events for the X Intrinsics. This is accomplished with a call to XtAppAddInput, supplying the port number from SPInit and a callback function. This initialization must be made early in the application, preferably in the INITIALLY rule in the D code.

The callback function should read the incoming message and act upon it. The action could be to send a D event to the dialog that handles the message, in which case the message handling is asynchronous. Alternatively, if a message is expected as the response to a previously sent message, the function used for sending the outgoing message could wait for the expected incoming message and then return to the caller. In this case the message handling is synchronous. You should be aware that this could lead to situations where the UI seems to hang, if the incoming message is not received within an expected or acceptable amount of time.

In general, asynchronous message handling is preferred.

 
Table of Contents Next Chapter