Chapter 4. Static Message Patterns

This chapter describes how to provide static message pattern information to the ToolTalk service. The ToolTalk service uses message patterns to determine message recipients. After receiving a message, the ToolTalk service compares the message to all current message patterns to find a matching pattern. Once a match is made, the message is delivered to the application listed in the message pattern.

You can provide message pattern information to the ToolTalk service using either dynamic or static methods, or both. The method you choose depends on the type of messages you want to receive.

Regardless of the method you choose to provide message patterns to the ToolTalk service, you will want to update these patterns with each current session and file information so that you receive all messages that refer to the session or file in which you are interested.

Message Pattern Attributes

The attributes in your message pattern specify the type of messages you want to receive and, to some extent, the number of messages you receive. You can supply multiple values for each attribute you add to a pattern. However, some attributes are set and have only one value.

Table 4-1 provides a complete list of attributes you can put in your message patterns.

Table 4-1. ToolTalk Static Message Pattern Attributes

Pattern Attribute

Value

Description

Category

TT_OBSERVE, TT_HANDLE,

Declares whether you want to perform the operation listed in a message or only view a message.

Scope

TT_SESSION, TT_FILE, TT_BOTH, TT_FILE_IN_SESSIO N

Declares interest in messages about a session or a file, or both; Join a session or file after the message pattern is registered to update the sessid and filename.

Arguments

arguments or results

Declares the arguments for the operation in which you are interested.

Class

TT_NOTICE, TT_REQUEST

Declares whether you want to receive notices or requests, or both.

File

char *pathname

Declares the files in which you are interested.

Object

char *objid

Declares what objects in which you are interested.

Operation

char *opname

Declares what operations in which you are interested.

Otype

char *otype

Declares the type of objects in which you are interested.

address

TT_PROCEDURE, TT_OBJECT, TT_HANDLER, TT_OTYPE

Declares what type of address in which you are interested.

disposition

TT_DISCARD, TT_QUEUE, TT_START

Instructs the ToolTalk service how to handle undeliverable messages to your application.

sender

char *procid

Declares the sender in which you are interested.

sender_ptype

char *ptype

Declares the type of sending process in which you are interested.

session

char *sessid

Declares the session in which you are interested.

state

TT_CREATED, TT_SENT, TT_HANDLED, TT_FAILED, TT_QUEUED, TT_STARTED, TT_REJECTED

Declares the state of the message in which you are interested.

All your message patterns must minimally specify:

  • Scope — Whether the application is interested in messages about a particular session or file.

  • Use TT_SESSION to receive messages from other processes in your session.

    • Use TT_FILE to receive messages about the file you have joined.

    • Use TT_FILE_IN_SESSION to receive messages for the file you have joined while in this session.


    Note: Messages that have a TT_BOTH scope will match your pattern if it has either TT_FILE or TT_SESSION.


  • Category — Whether the application wants to perform operations listed in messages or only view messages.

    • Use TT_OBSERVE if you only want to view messages.

    • Use TT_HANDLE to if you want to perform operations listed in the message.

The ToolTalk service compares message attributes to pattern attributes as follows:

  • If no pattern attribute is specified, the ToolTalk service counts the message attribute as matched. The fewer pattern attributes you specify, the more messages you become eligible to receive.

  • If there are multiple values specified for a pattern attribute, one of the values must match the message attribute value. If no value matches, the ToolTalk service will not consider your application as a receiver.

This chapter describes how to provide process and object type information to Static Message Patterns.

Defining Static Messages

The static messaging method provides an easy way to specify the message pattern information if you want to receive a defined set of messages.

To use the static method, you define your process types and object types and compile them with the ToolTalk type compiler, tt_type_comp. When you declare your type information, the ToolTalk service creates message patterns based on the information. These static message patterns remain in effect until you close communication with the ToolTalk service.

Defining Process Types

Your application can still be considered a potential message receiver even when no process is running the application. To do this, you provide message patterns and instructions on how to start the application in a process type (ptype) file. These instructions tell the ToolTalk service to perform one of the following actions when a message is available for an application but the application is not running:

  • Start the application and deliver the message

  • Queue the message until the application is running

  • Discard the message

To make the information available to the ToolTalk service, the ptype file is compiled with the ToolTalk type compiler, tt_type_comp, at application installation time.

When an application registers a ptype file with the ToolTalk service, the message patterns listed in it are automatically registered, too.

The ptype provides application information that the ToolTalk service can use when the application is not running. This information is used to start your processes if necessary, to receive a message, queue messages until the process starts, or deliver TT_PROCEDURE-addressed messages to your process.

A ptype begins with a process-type identifier (ptid). Following the ptid are:

  1. An optional start string — the ToolTalk service will execute this command, if necessary, to start a process running the program.

  2. Signatures — Describes the procedure and process messages that the program wants to receive. Messages to be observed are described separately from messages to be handled.

Signatures

Signatures describe the procedure and process messages that the program wants to receive. A signature is divided by an arrow (=>) into two parts. The first part of a signature specifies matching attribute values. The more attribute values specified in a signature, the fewer messages the signature will match. The second part of a signature specifies receiver values that the ToolTalk service will copy into messages that match the first part of the signature.

A ptype signature can contain values for disposition and operation numbers (opnum). The ToolTalk service uses the disposition value (start, queue, or the default discard) to determine what to do with a message that matches the signature when no process is running the program. The opnum value is provided as a convenience to message receivers. When two signatures have the same operation name but different arguments, different opnums makes incoming messages easy to identify.

Creating a Ptype File

The following code example shows the syntax for a ptype file

ptype::='ptype' ptid `{' 
      property*  
      [`observe:' psignature*]
      [`handle:' psignature* ]
      `}' [`;']
property::=property_id value `;'
property_id::=`per_file'
   |`per_session'
   |`start'
value::=string
   |number
ptid::= identifier
psignature::=[scope] op args
       [`=>'
       [`start'][`queue']
       [`opnum='number]]
       `;'
scope:=`file'
   |`session'
   |`file_in_session'
args::=`(` argspec {, argspec}* `)'
   |`(void)'
   |`()'
argspec::=mode type name
mode::=`in' | `out' | `inout'
type::=identifier
name:=identifier

Property_id Information

ptid 


process type identifier (ptid). Identifies the process type. A ptid must be unique for every installation. Because this identifier cannot be changed after installation time, each chosen name must be unique. For example, you can use a name that includes the trademarked name of your product or company, such as Sun_EditDemo. The ptid cannot exceed 32 characters and should not be one of the reserved identifiers: ptype, otype, per_file, per_session, start, opnum, queue, file, session, observe, or handle.

per_file  


The maximum number of processes of this type that can concurrently observe a particular file. If the maximum number processes of this type are already observing a file, the ToolTalk service will not start another one.

Set this limit to 1 for tools that cannot handle multiple processes updating the same file.

per_session  


The maximum number of processes of this type that can concurrently run in a single session. If maximum number of processes of this type are already running in a session, the ToolTalk service will not start another one.

Set this limit to 1 for tools that manage multiple files in one process. All files will then be handled by a single process in each user session.

start  


Start string for the process. If the ToolTalk service needs to start a process, it executes this command; /bin/sh is used as the shell.

Before executing the command, the ToolTalk service defines _SUN_TT_FILE as an environment variable with the value of the file attribute of the message that caused the application to be started. The _SUN_TT_FILE value has the following format: hostname:pathname, even though the file attribute is a pathname. This command runs in the environment of ttsession, not in the environment of the sender of the message that started the application, so any context information must be carried by message arguments.

Psignature Matching Information

op 


Operation name. This name is matched against the op attribute in messages.


Note: If you specify message signatures in both your ptype and otypes, use unique operation names in each. For example, do not specify a display operation in both your ptype and otype.


args 


Arguments for the operation. If the args list is (void), the signature matches only messages with no arguments. If the args list is empty (just “()”), the signature matches matches without regard to the arguments.

scope 


This pattern attribute is matched against the scope attribute in messages.

Psignature Actions Information

start 


If the psignature matches a message and no running process of this ptype has a pattern that matches the message, start a process of this ptype.

queue 


If the psignature matches a message and no running process of this ptype has a pattern that matches the message, queue the message until a process of this ptype registers a pattern that matches it.

opnum 


Fill in the message's opnum attribute with the specified number. The opnum enables you to specify an operation more than once and list unique arguments with each instance of the operation.

The following sample code illustrates a ptype file.

#include "Sun_EditDemo_opnums.h"

ptype Sun_EditDemo {
   /* setenv SUN_EDITDEMO_HOME to install dir for the demo */
    start“${SUN_EDITDEMO_HOME}/edit”;
    handle:
    /* edit file named in message, start editor if necessary */
    session Sun_EditDemo_edit(void)
                => start opnum=SUN_EDITDEMO_EDIT;

    /* tell editor viewing file in message to save file */
    session Sun_EditDemo_save(void)
                => opnum=SUN_EDITDEMO_SAVE;

    /* save file named in message to new filename */
    session Sun_EditDemo_save_as(in string new_filename)
                => opnum=SUN_EDITDEMO_SAVE_AS;
    /* bring down editor viewing file in message */
    session Sun_EditDemo_close(void)
                => opnum=SUN_EDITDEMO_CLOSE;
};

The Sun_EditDemo_opnums.h file defines symbolic definitions for all the opnums used by edit.c, allowing both the edit.types file and edit.c file to share the same definitions.

The following sample code illustrates a ptype file for the ttsample2_sgi example:

/* ttsample2_sgi_ptypes - ptype definitions for ttsample2_sgi example */
#include “ttsample2_sgi_opnums.h”
ptype TTSAMPLE2
{
 start “/usr/tmp/ttsample2_sgi_service”;
 handle:
    session ttsample2_value(in int send, out int receive)
                       => start opnum=TTSAMPLE2_VALUE;
};

Defining Object Types

When a message is addressed to a specific object or a type of object, the ToolTalk service must be able to determine to which application the message is to be delivered. Applications provide this information in an object type (otype) file. An otype file contains the ptype information of the application that manages the object and message patterns that pertain to the object.

These message patterns also contain instructions that tell the ToolTalk service what to do if a message is available but the application is not running. In this case, ToolTalk performs one of the following instructions:

  • Start the application and deliver the message

  • Queue the message until the application is running

  • Discard the message

To make the information available to the ToolTalk service, the otype file is compiled with the ToolTalk type compiler tt_type_comp at application installation time. When an application that manages objects registers with the ToolTalk service, it declares its ptype. When a ptype is registered, the ToolTalk service checks for otypes that mention the ptype and registers the patterns found in these otypes.

The otype for your application provides addressing information that the ToolTalk service uses when delivering object-oriented messages. The number of otypes you have, and what they represent, depends on the nature of your application. For example, a word processing application might have otypes for characters, words, paragraphs, and documents; a diagram editing application might have otypes for nodes, arcs, annotation boxes, and diagrams.

An otype begins with an object-type identifier (otid). Following the otid are:

  1. An optional start string — ToolTalk will execute this command, if necessary, to start a process running the program.

  2. Signatures — Code that defines the messages that can be addressed to objects of the type (that is, the operations that can be invoked on objects of the type).

Signatures

Signatures defines the messages that can be addressed to objects of the type. A signature is divided by an arrow (=>) into two parts. The first part of a signature defines matching criteria for incoming messages. The second part of a signature defines receiver values which the ToolTalk service adds to each message that matches the first part of the signature. These values specify the ptid of the program that implements the operation and the message's scope and disposition.

Creating Otype Files

The following code sample shows the syntax for an otype file.

otype         ::= obj_header'{' objbody* '}' [';']
obj_header    ::= 'otype' otid [':' otid+]
objbody       ::= `observe:' osignature*
       |    `handle:' osignature*

osignature    ::= op args [rhs][inherit] `;'
rhs           ::= [`=>' ptid [scope]]
                  [`start'][`queue']
                  [`opnum='number]
inherit       ::= `from' otid
args          ::= `(` argspec {, argspec}* `)'
              |   `(void)'
              |   `()'
argspec       ::= mode type name
mode          ::= `in' | `out' | `inout'
type          ::= identifier
name          ::= identifier
otid          ::= identifier
ptid          ::= identifier

Obj_Header Information

otid 


object type identifier (otid). Identifies the object type. An otid must be unique for every installation. Because this identifier cannot be changed after installation time, each chosen name must be unique. For example, begin with the ptid of the tool that implements the otype. The otid is limited to 64 characters and should not be one of the reserved identifiers: ptype, otype, per_file, per_session, start, opnum, start, queue, file, session, observe, or handle.

Osignature Information

The object body portion of the otype definition is a list of osignatures for messages about the object that your application wants to observe and handle.

op 


Operation name. This name is matched against the op attribute in messages.


Note: If you specify message signatures in both your ptype and otypes, use unique operation names in each. For example, do not specify a display operation in both your ptype and otype.


args 


Arguments for the operation. If the args list is (void), the signature matches only messages with no arguments. If the args list is empty (just “()”), the signature matches messages without regard to the arguments.

ptid 


Process type identifier for the application that manages this type of object.

opnum 


Fill in the message's opnum attribute with the specified number. The opnum enables you to specify an operation more than once and list unique arguments with each instance of the operation.

inherit 


Otypes form an inheritance hierarchy in which operations can be inherited from base types. The ToolTalk service requires the otype definer to explicitly name all inherited operations and the otype from which to inherit. This explicit naming prevents later changes (such as adding a new level to the hierarchy, or adding new operations to base types) from unexpectedly affecting the behavior of an otype.

scope 


This pattern attribute is matched against the scope attribute in messages. It appears on the rightmost side of the arrow and is filled in by the ToolTalk service during message dispatch. This means the definer of the otype can specify the attributes instead of requiring the message sender to know how the message should be delivered.

Osignature Actions Information

start 


If the osignature matches a message and no running process of this otype has a pattern that matches the message, start a process of this otype.

queue 


If the osignature matches a message and no running process of this otype has a pattern that matches the message, queue the message until a process of this otype registers a pattern that matches it.

The following sample code illustrates an otype file.

Include "Sun_EditDemo_opnums.h"
otype Sun_EditDemo_object {
   handle:
   /* hilite object given by objid, starts editor 
      if necessary */
   hilite_obj(in string objid)
   => Sun_EditDemo session start opnum=SUN_EDITDEMO_HILITE_OBJ;
};

The Sun_EditDemo_opnums.h file defines symbolic definitions for all the opnums used by edit.c, allowing both the edit.types file and edit.c file to share the same definitions.

Installing Type Information

The types database makes ptype and otype information available on the host that executes the sending process, the host that executes the receiving process, and the hosts that run the sessions to which the processes are joined.

  • To start applications and to queue messages, the ptype definition must be placed into the types database.

  • To receive messages addressed to objects your application creates and manages, the otype definitions must also be installed in the types database.

To place your type information into the xdr format types database and make it available to the ToolTalk service, you compile your type files with the ToolTalk type compiler, tt_type_comp. This compiler creates the types database definitions for your type information and stores them in the types database.

To install an application's ptype and otype, run tt_type_comp on your type file:

      % tt_type_comp <your-file>

tt_type_comp runs your-file through cpp, compiles the type definitions, and merges the information into the types database.

By default, tt_type_comp uses the user database. To specify another database, use the -d option; for example:

       % tt_type_comp -d user|system|network <your-file>

For more information on tt_type_comp, see the man page.


Note: When you run tt_type_comp on your ptype or otype files, it first runs cpp on the file and then checks the syntax before it places the data into the XDR format. If syntax errors are found, a message is displayed that indicates the line number of the cpp file. To find the line, enter


 cpp -P  source-file  temp-file

and view the temp-file to find the error on the line reported by tt_type_comp.

Making Type Information Available to the ToolTalk Service

After you run tt_type_comp, you need to make your type information available to the ToolTalk service. To do this, tell the ToolTalk service to read the type information in the types database as follows:

  1. Enter the ps command to find the process identifier (pid) of the ttsession process.

    % ps -elf | grep ttsession 
    

  2. Enter the kill command to send a SIGUSR2 signal to ttsession.

    % kill -USR2 <ttsession pid> 
    

Declaring Process Type

Since type information is only specified once (when your application is installed), your application needs to only declare its ptype each time it starts.

To register your ptype information with the ToolTalk service, use tt_ptype_declare() during your application's ToolTalk initialization routine. The ToolTalk service will read the type information and create the message patterns listed in your ptype and any otypes that reference the specified ptype.

The message patterns created when you declare your ptype information exist in memory until your application exits the ToolTalk session.


Note: The message patterns created when you declare your ptype information cannot be unregistered with tt_pattern_unregister().

The following code sample registers its ptype during its edit.c program initialization.

/*
 * Initialize our ToolTalk environment.
 */
int
edit_init_tt()
{
        int     mark;
        char    *procid = tt_open();
        int     ttfd;
        void    edit_receive_tt_message();
 
        mark = tt_mark();
 
        if (tt_pointer_error(procid) != TT_OK) {
                return 0;
        }
        if (tt_ptype_declare(“Sun_EditDemo”) != TT_OK) {
                fprintf
          (stderr,”Sun_EditDemo is not an installed 
              ptype.\n”);
                return 0;
        }
        ttfd = tt_fd();
        notify_set_input_func(edit_ui_base_window, 
                      (Notify_func)edit_receive_tt_message,
                       ttfd);
 
        tt_session_join(tt_default_session());
 
        /*
         * Note that without tt_mark() and tt_release(), the 
         * above combination would leak storage 
         * tt_default_session() returns a copy owned by the 
         * application, but since we don't assign the
         * pointer to a variable we could not free it
         * explicitly.
         */
 
        tt_release(mark);
        return 1;
}

The following code sample registers its ptype during its ttsample2_sgi_service.c program initialization.

/* declare ptype
 * note there is no dynamic pattern registration
 */
if (tt_ptype_declare(“TTSAMPLE2”) != TT_OK)
   {
    /* TTSAMPLE2 is not an installed ptype */
    fprintf(stderr, “No TTSAMPLE2 type for ToolTalk\n”);
    exit(-1);
   }

Data Type Registration

Your application will use either process-oriented messages or object-oriented messages to communicate with other applications. To send messages to types of processes, types of objects, and specific objects, ptypes (for process-oriented messages) and otypes (for object-oriented messages) are required. This type information is compiled at application installation time and stored in the types database.

To communicate with other vendors' applications, you must know their ptypes and possibly their otypes (depending on the method of messaging you choose).