Thursday, November 17, 2011

Restructuring of Framework Remote Component Update 1


Restructuring of Framework Remote Component Update 1


Lack of Topic Data Buffer Release

Immediately after publishing the last post – Restructuring of Framework Remote Component – I found that Remote Register Complete topic still wasn't treated correctly in all circumstances.

Looking into this I finally found that it didn't really have anything to do with this topic per se.  Instead, it was due to a topic that the framework, upon its being published, determines that it is to be transmitted.  When this is the case the framework copies the data to a record that is added to the Transmit Queue and invokes a procedure to release the data buffer.

The problem is that the Release procedures, except for one, only release the data buffer if it has been marked as being read; i.e., that a Reader has been instantiated for the topic instance.  When the framework just copies it into the Transmit Queue this doesn't happen.  Therefore, the data buffer wasn't being released.  Since the topic was specified as one to use multiple buffers the next time a writer for the topic was instantiated for the same producer another data buffer was assigned. 

Since the Remote component is both the publisher and the consumer of this topic, a new buffer could be assigned upon the publish of a received message from another application.  Then, when Remote, as the consumer component, read the topic it got the oldest of the multiple data buffers.  Depending upon the timing, this could be the instance that the application transmitted to another app rather than the one received.

In trying to determine why this was taking place I happened to see the one Release procedure that also checked whether the Reference Numbers matched when the Being Read boolean was not set.  I reasoned that this was because at some time in the past I had found the same problem for a different method of topic delivery and had corrected the problem in this manner.  That is, looking for a matching Reference Number when the topic didn't have Being Read set indicating that it had been transmitted rather that delivered to a local component that had instantiated a Reader.

I updated each of the various Release procedures to also make a similar check if the procedure was being called following transmit.  This fixed the problem.


Use of Remote Register Complete message

While locating the source of the seeming mis-delivery of the Remote Register Complete topic, the reason for needing this topic was well illustrated.  That is, the Aperiodic component of App2 sent a N-to-One request to App1 each time that it ran if there was a connection to App1.  However, until the Remote Register messages were received and treated sometime after the connection, the remote app – in this instance App1 – didn't know what to do with the Response.

Therefore, the response wasn't transmitted back to App2 and its data buffer didn't get released.  In this situation the topic wasn't one that specified multiple data buffers.  Therefore, the next time such a topic was received from App2, the response couldn't be created because the data buffer was still in use.

Also, a table exists to match responses to received requests to look up where to transmit the response.  With no response to match a request, received requests kept being added to the table until its limit was reached.

This was fixed – as point 4) in the previous post mentioned that it would be – by changing when the Writer could obtain a data buffer for a topic to be transmitted.  Instead of only requiring that there be a connection to the remote app that is to consume the topic, another consideration was added.  When the topic is a non-registration topic, Remote Register Complete also has to have been received from the remote app to which the topic message is to be transmitted.

This prevented topic data buffers being created, and hence written and published, until the remote application is ready to fully treat them.

Tuesday, November 8, 2011

Restructuring of Framework Remote Component


Restructuring of Framework Remote Component

 Now that the treatment of the message protocol for communications between the user applications and the display application had been incorporated into the mC framework it became time to restructure the Remote Component to treat the interface to the Display application using the same Ada packages and methods as those for other User applications. 

This took me longer than expected and is not yet finished.  Mostly however because some features were also added that are not strictly related to employing the user application Remote methods in common with the display interface to avoid the duplication that occurred when the cloned user display components were moved into the framework Remote component.  Four of these were

   1) to get application App3 that contains C and C++ user components up-to-date after having been ignored for quite some time while a number of framework changes were being made.
   2) to use Windows interfaces to check which of the other applications of the configuration of the current PC are running,
   3) to use Windows to do the same for a different PC in the configuration,  and
   4) to send a Remote Register Complete topic between running user applications to indicate to a connected application that the sending application has completed its Remote Registration with the receiving application.  Sometime in the future this can be used to avoid transmitting other topics until the sending application is able to determine that the connected application has completed its remote registration with the sending application and hence is ready to treat remote topics.

Another feature to be added will be to monitor the communications between the user application and the display application to check that the two applications remain connected or, if become reconnected, to continue as best as possible from where communications was lost.  Yet another (structure only change) will be to package the remote registration procedures into a Registration unit for easier recognition of their common rationale.

An unrelated additional feature will be to have the first running application of the configuration launch the others.

As part of this change, the configuration file was changed to have a user applications portion and a display applications portion so that one such file can be used both by the user application framework and by the display application.  The user application framework needed this change as part of incorporating the treatment of the display interface via the same methods as the user applications.

While making these changes an error was detected where the application identifier was treated (in various places) as an index into arrays of data concerning applications of the configuration and connected applications.  This previously had not become apparent since the debug cases had been for user applications 1, 2, and 3.  When I added the display application for common treatment, I separated the possible values for the identifiers into one range values for user applications and another range for display applications.  Thus the display application came to be assigned an identifier of 15 while the arrays were sized as 1 to 5 so that a direct index of the identifier could no longer be used.  Further, I could find this sort of thing better if I switched app 2, for instance, to app 5 to have gaps in the user app identifiers which I will need to do.
Above is a figure showing how the user Display components were previously moved into a common framework Display component. 

The following second figure illustrates how the Display interface now uses the same Methods as the user components and how, in the future, it will use the same communications Monitor package and package the remote registration into its own unit.
The new diagram is meant to show that the Remote Component with its thread (the top middle oval to indicate the thread – enclosed icon to indicate the Ada package) includes inputs from and outputs to the tables and reads the Transmit, Receive and Watch Queues upon receiving a wakeup event (that is, the notify of a dataless topic that is published as part of adding the entry to the queue).

The Transmit Queue is written via the publish of a topic from various components while the Receive Queue is written to contain messages received from other applications including the Display App via the receive ports of the MS_Pipe and WinSock communication methods that each have a thread that blocks to wait for a new message from its associated application. 

Received display messages are passed to the Display subpackage that converts them to instances of the Display Event Request topic message and then publishes them for distribution.  In this case the Remote component also queues to the Transmit Queue. 

A received Display Event Response topic (dequeued from the Receive Queue) as well as an unsolicited Display Command topic message are treated via Display as received by the framework (while running under the publishing component's thread).  The Display package supplies the Display protocol header in place of that of the Topic protocol and transmits to the display app via the selected Remote Method.

Hence the Display package is the Display Protocol to Topic Protocol converter and vice versa.  This design, as mentioned in the previous post, allows for the use of other protocols to be added; such as an A661 Protocol.  Only another protocol converter need be added, just as can be done for communication methods, by adding another supported method to be selected by the Method package.  When this becomes necessary a protocol selector package should be added to invoke callback procedures of the particular converter package as is done by Method to select those of MS_Pipe or WinSock.  Other communication drivers can, of course, be added as well where Method would then also contain callback procedure entries to the new method.

Monitor / Registration

The Monitor package will be discussed after monitoring of the user-display application traffic has been implemented.  The Registration package will just be grouping the remote register procedures within such a package. 

Windows Interface to Detect Running Applications

There are supposed to be newer Windows interfaces to return whether a particular process (that is, application) is running on the current PC or on a named one.  Others to start a process on the current PC. 

Since these interfaces don't seem to be available via the GNAT libraries (and certainly not via Win32Ada that contains interfaces to much older versions of Windows), I attempted to access them through a Visual C++ function and link it via gnatlink with the rest of exploratory project.  After various attempts I put that aside to return to later.

I can, however, detect if a specific application is currently running via the Windows interfaces provided with GNAT and Win32Ada.
  BOOL WINAPI EnumProcessModules
  ( __in   HANDLE hProcess,
    __out  HMODULE *lphModule,
    __in   DWORD cb,
    __out  LPDWORD lpcbNeeded
  );
can be used.  To do this, the appRunningC.c function was created and imported to Ada via
  pragma Import(C, App_Running, "appRunningC");

The Ada declaration used was
  function App_Running
  ( Application : in Interfaces.C.Strings.Chars_Ptr
  ) return Interfaces.C.char;
where the Chars_Ptr is used to point to a null terminated character array containing the name of the application along with its path as obtained from the Apps-Configuration.dat file.  The returned character is typecast to a byte value to indicate whether the application is running or not.

The code of appRunningC is
#include <mC-ItfC.h>
#include <ctype.h>
#include <psapi.h>
#include <stdio.h>
#include <string.h>
#include <tchar.h>
#include <windows.h>


// Microsoft Help comment:
//   To ensure correct resolution of symbols, add Psapi.lib to TARGETLIBS
//   and compile with -DPSAPI_VERSION=1
// My comment:
//   For GNAT, include C:\GNAT\2011\lib\gcc\i686-pc-mingw32\4.5.3\libpsapi.a
//   in the gnatlink command. 


void strConvert( char * inStr, char * outStr )
{ // Convert string to all lower case while switching any forward slash
  // in pathname to a backward slash
  int i = 0;
  while (inStr[i] != 0)
  {
     if (inStr[i] == '/')
     { outStr[i] = '\\';
     }
     else
     { outStr[i] = tolower(inStr[i]);
     }
     i++;
  } // end loop
  outStr[i] = 0; // attach trailing null


} // end method strConvert 


int MatchModulePathname( DWORD processID, char * Application )
   { // Check application name at beginning of module list for process for match.


    HMODULE hMods[1024];
    HANDLE hProcess;
    DWORD cbNeeded;
    unsigned int i;


    // Get a handle to the process (that is, application).
    hProcess = OpenProcess( PROCESS_QUERY_INFORMATION |
                            PROCESS_VM_READ,
                            FALSE, processID );
    if (NULL == hProcess)
        return 0; // false


    // Get a list of all the modules in this process.
    if ( EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded) )
    {


        // Only the first name will contain the application name of the process.
        TCHAR szModName[MAX_PATH], ModName[MAX_PATH];


        // Get the full path to the module's file.
        if ( GetModuleFileNameEx( hProcess, hMods[0], szModName,
             sizeof(szModName) / sizeof(TCHAR)) )
        {
            strConvert( szModName, ModName );


            // Check if module name with path matches that of the Application.
            if (strcmp(Application,ModName) == 0)
            {
               // Release the handle to the process and return found.
               CloseHandle( hProcess );
               return 1; // true
            }
        }


    } // end if ( EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded) )


    // Release the handle to the process.
    CloseHandle( hProcess );
    return 0; // false


} // end method MatchModulePathname


extern "C" char appRunningC(char * Application )
{ // Determine if Application is running.
    DWORD aProcesses[1024];
    DWORD cbNeeded;
    DWORD cProcesses;
       unsigned int i;


    // Get the list of process identifiers.
    if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) )
        return 2; // Application cannot be found due to problem


    // Calculate how many process identifiers were returned.
    cProcesses = cbNeeded / sizeof(DWORD);


    // Examine module names for each process for match to input.
    char AppPath[MAX_PATH];
        strConvert(Application, AppPath);
         for ( i = 0; i < cProcesses; i++ )
         {
            if (MatchModulePathname( aProcesses[i], AppPath ) == 1)
            {
                return 1; // Application found
            }
        }


    return 0; // Application not found


} // end method appRunningC

This routine is currently being used to check whether each application of the configuration (other than the application that is doing the checking) is running.  This can be changed to pass a list of all of the other applications in the configuration to appRunningC and return an array of those that are running to avoid multiple calls to the OpenProcess and EnumProcessModules functions.

GNAT Compiler

While making the various changes it seemed that GNAT GPS no longer rebuilt changed separates.  This seemed to be the case after the addition of the C function for use by the Ada framework Remote-Method-MS_Pipe package to interface to Windows to check what applications of the configuration were running.  Therefore I had to start compiling the packages that I changed with statements such as
c:\gnat\2011\bin\g++ -c -g -IC:\Source\EP\UserApp\Try10 -IC:\Source\EP\Util
  -IC:\Win32Ada\src -aLC:\Source\EP\ObjectC
  C:\Source\EP\UserApp\Try10\mc-message-remote.adb -o mc-message-remote.o
in a batch file (where the indented lines are actually part of the first line) as well as the .c file.  The -g switch includes debug symbols in the .o object file to be included in the eventual .exe file by gnatlink.

Remote Register Complete topic

The implementation of the Remote Register Complete topic took longer than expected.  This topic is both produced and consumed by the Remote framework component.  However, the instance produced by the Remote component of one application is meant for that of another application. 

Therefore the topic used the recently added Requested Delivery method of message exchange so each application could register to consume a delivery identifier that equaled its application identifier.  The Remote component of the publishing application supplies the delivery identifier of the application to receive the topic as it publishes the topic.  Therefore there are as many possible publishers of the topic as there are applications and the same number of consumers.

This is as the message exchange delivery method was intended to treat.  The difference in this case was that the same component was both a publisher and a consumer so its Role was Either.  Since this Role hadn't been previously used, this caused a few problems that had to be tracked down and corrected.  However, another problem caused confusion in identifying what problems were caused by this new role.

That was due to one application of a pair seeming to transmit its instance of the topic to the other application and that application seeming to create its instance but not doing the transmit.  Finally (I must be getting old) I identified the reason.

The registering of a delivery identifier to be consumed involves, as has been done in the past, two variables where the second one is referenced in the Register call.  The first of these is an array of identifier pairs indicating five possible pairs of delivery identifiers that indicate the identifiers the component is to treat.  Each pair indicates a range of values where the second entry can be 0 to indicate that there is no range; only the particular identifier of the first entry.  The second variable contains the count of the number of pairs to examine and the doubly indexed array of values.  Normally, of course, the count will be one.

Registering to consume the Remote Register Complete topic, the Remote Install procedure declared
    Delivery_Id_List
    --| Treat all "Remote Register Complete Topic" messages with ids of the app
    : mC.Itf_Types.Delivery_Id_Array_Type
    := ( ( 1, 1 ), ( 0, 0 ), ( 0, 0 ), ( 0, 0 ), ( 0, 0 ) );
    Delivery_Id
    --| Deliver topic when identifier is that of local app
    : mC.Itf_Types.Delivery_List_Type
    := ( Count => 1,
         List  => Delivery_Id_List );
mimicking what had been done in the past for other Requested Delivery and Delivery Identifier delivery methods.  Except in those cases, the Delivery_Id_List object was declared as constant since the identifiers were known at compile-time. 

In this case, since the pair of delivery ids depends upon the application's own identifier – that isn't known until initialization-time, the value was initialized as shown above and then modified just prior to the Register call to contain the running application's id as shown below.


  Delivery_Id_List := ( ( Integer(Local_App.Id), Integer(Local_App.Id) ),
                        ( 0, 0 ), ( 0, 0 ), ( 0, 0 ), ( 0, 0 ) );


  mT.Remote_Register_Complete_Topic.Request.Data.Register
  ( Participant => Component_Main_Key,
    Detection   => mC.Itf_Types.Event_Driven,
    Role        => mC.Itf_Types.Either,
    Delivery_Id => Delivery_Id,
    Callback    => Monitor.Treat_Register_Complete'access,
    Access_Key  => Remote_Register_Complete_Topic_Access_Key,
    Status      => Data_Status );
where the Count in the Delivery_Id variable remains as 1.

Since this kind of Register (other than the use of Either for the Role instead of Consumer) had been working on the order of a year or more it didn't occur to me that this late resetting of the Delivery_Id_List could be causing any problems. 

However, I finally determined that the compiler was ignoring the resetting of the value to be used by Delivery_Id in the object code that it generated.  So both applications of the pair were specifying that they would consume delivery id 1.  I changed the source code to


  declare


    Delivery_Id_List
    --| Treat all "Remote Register Complete Topic" messages with ids of the app
    : mC.Itf_Types.Delivery_Id_Array_Type
    := ( ( Integer(Local_App.Id), Integer(Local_App.Id) ),
         ( 0, 0 ), ( 0, 0 ), ( 0, 0 ), ( 0, 0 ) );


    Delivery_Id
    --| Deliver topic when identifier is that of local app
    : mC.Itf_Types.Delivery_List_Type
    := ( Count => 1,
         List  => Delivery_Id_List );


  begin

    mT.Remote_Register_Complete_Topic.Request.Data.Register
    ( Participant => Component_Main_Key,
      Detection   => mC.Itf_Types.Event_Driven,
      Role        => mC.Itf_Types.Either,
      Delivery_Id => Delivery_Id,
      Callback    => Monitor.Treat_Register_Complete'access,
      Access_Key  => Remote_Register_Complete_Topic_Access_Key,
      Status      => Data_Status );


  end;

This fixed the problem with Remote of each application transmitting the instance of the topic that was published by it to the other application of the pair where it was then delivered to the
Treat_Register_Complete procedure of the Monitor subpackage.

This might be a case that could have been fixed by pragma Volatile if it had been recognized.  That is, an example of the same thing that can happen when an object is changed by one thread and read by another without the new value being used by the code that was generated by the compiler due to its not recognizing that it could be changed.  (Or, as happens when an address is passed to a procedure that then uses it to change a value used later by the calling routine.)

The remaining gotchas were then immediately found and fixed.

Wednesday, September 21, 2011

Display Protocol Moved to Framework and Added Message Exchange Method


Background

As part of the monitoring of the Exploratory Project communications in order to detect a dropped connection I decided it was time to move the treatment of the communications with the Display application from user components to the framework.  This was overdue since, with the addition of a second user application to interface to the display application, the user component had to be cloned and would have to be cloned again for every user application that needs to interface with the Display application.  And, as part of the framework, additional protocols can be supported (as specified in the configuration files) and additional communication interfaces such as the WinSock interface supported for communications between user applications.

When I did this I got a surprise due to a fading of my memory of what I had had to do when I had added the second user application to interface with the display.  With the making of the user component into a framework component I had to remove my cloned topics that the user components supported so as to have only one Display Widget Event topic to translate a display protocol event message into a framework topic.  This because can't continue to add cloned topics since now a part of what should be a stable framework.  Therefore, it was necessary to come up with a way that the common framework of each user application could determine when the Display Widget Event topic needed to be forwarded to a remote user app when the local app also had a consumer for the topic.

In addition, the move of the display protocol to the framework highlighted another problem with the previous framework topics.  That is, I originally created the Delivery Identifier message exchange topic category knowing that I wanted to be able to forward a display widget event to the particular component that registered to treat the particular event identifier.  That is, one topic produced by possibly multiple components and only delivered to the one of multiple potential consumers that registered to treat the particular delivery identifier.

When it came time to actually implement this the treating component had to send a display update command topic to be translated to the display protocol message to be transmitted to the display application.  At the time, this was handled by using a Request / Response message exchange topic category (with no response requested) with the particular user display component registering to consume the request.  Again, with the display component becoming part of the framework, it would only be able to register for a common single such topic since not able to treat extra cloned topics as additional user applications interface to the display.

This again was something I should have recognized at the time that I added the interface of the user application with the display and had to have the user component respond to the received widget event.

Requested Delivery Message Exchange

Therefore, while implementing a common Display Widget Event topic to be published by the framework display component upon the receipt of the display protocol message, I created a new message exchange topic category of Requested Delivery.  This category combines Delivery Identifier and Request / Response where there can be multiple producers of the topic (in this particular case the multiple instantiations of the framework display component – one per user application) and multiple consumers with only one particular consumer registering to treat a particular delivery identifier.  This is the same as Delivery Identifier.  In addition, there is a paired response topic as with Request / Response where the response is returned to the particular request publisher. 

Instead of One-of-N delivery (one consumer of N possible) as with Delivery Identifier and N-to-One delivery (N producers to one possible consumer with the response returned to the particular request producer) as with Request / Response, there is One-of-N-to-One delivery where the message is delivered to one consumer of N possible consumers and the response is delivered to the particular request producer.

Therefore, the framework of one user application can receive a Widget Event message from the Display application, translate it to the common Display Widget Event topic and publish it.  The framework then determines which component of what application registered to treat the widget id of the message and forwards it to that component.  The component treats the event and creates the new instance of the response topic and publishes it.  The framework then returns the topic instance to the component that published the request.  Since this will be the framework display component of a particular user application, it converts it to a display protocol message and transmits it to the Display application.

The implementation of this new Requested Delivery message exchange resulted in a number of challenges to be solved.  That is, when there were cloned topics, the consumer of a particular delivery id by a particular component could be determined at topic registration time and the publisher of the particular cloned topic was known.  With the change to Requested Delivery, the consumer can be known but not the particular producer since the delivery id to be produced isn't known until it is received from the Display app and hence published by the framework display component.  For instance, the framework Display component of each user application will register as the producer of the Display Widget Event request message.

The registration of the producer of a particular delivery identifier has to be delayed until the topic is actually published with the delivery id although it continues to register as a producer of the topic in general at registration time.  To do this, another group of items was added to the Register Request messages exchanged by the user apps along with tables to know what components have registered to consume particular delivery ids.  This group of items contains all the components that have registered to consume the Requested Delivery topic along with the delivery ids that each component has registered to consume.  Then, when a topic is published, the table created due to these lists can be used to determine what application registered to consume the particular identifier.

If the consuming component is in a remote application, the framework sends the topic to that application.  The framework of that application then looks it up in the table used prior to this change to determine the component to which to forward the topic.  If not in that table, it registers the topic and component as specified in the newly added table so it can be processed in the usual way for the response and any additional instances can be found as received.  That is, the producer of the delivery id is now known so the framework can determine the component to which to return the response.

With these changes, messages such as those received from the display can be forwarded to a user component that has raised its hand (registered) to treat a particular instance of the topic (as identified by a numeric value) and the resulting response message can be returned.  And there can be multiple components that produce the topic although, hopefully, not with the same numeric identifier. 

This is the case with the ARINC-661 protocol where different layers can be interfaced with different user applications – one layer to one user application.  Or, with the ARINC supplement 3 draft document (http://wn.com/ARINC_661), one application treating multiple layers as long as the widget identifiers of the layers are unique.  There must also be other examples where this new message exchange category can be applied.
 

Framework Component Structure

The structure of the components of the framework that are directly involved with communications is illustrated in the Framework Components diagram.

Note, framework components are similar to user components except for being an integral part of the component.  That is, they register as a component with the framework, register the topics that they will produce and consume, have a process/thread in which to execute, etc.  They are dissimilar in that they can reference various framework types and variables.

As shown in the diagram, there is a Remote package installs itself as a component while requesting that its non-install code run under a Remote process thread.  In this package are a group of tables that are used to determine topics to be transmitted and validate received messages as to whether they are expected.  (If not, they are rejected.) 

Validated received messages (each received in one of the Receive process threads of MS_Pipe or WinSock packages – one thread per possible remote user application) are added to the Receive Queue and with the framework then signaled to run the Remote thread.  This also updates the Connections package watch tables used to monitor whether reconnect attempts are needed.


Messages to be transmitted are added to the Transmit Queue and the framework is signaled to run the Remote thread.  (Each time the thread is run it checks both queues.)  Messages in the Transmit Queue are passed along to the Method package to transmit the message by each supported and connected communication method as implemented in transmit procedures of the MS_Pipe and WinSock packages.

The framework also wakes up the Remote thread periodically to send heartbeat messages in case components haven't queued Topic messages to be transmitted.

The Display interface is implemented within a Display package.  It installs Client and Response components where its install registers with the framework to provide corresponding Client and Response process threads.  Received display messages are translated to Requested Delivery request topic messages in the Parse package and then published for the framework to deliver to the consumer of the widget identifier.   The Client component acts as if it is the Response component when doing the publish so that the response will be delivered to the Response component.  The Response component then transmits the response, via the display protocol, to the Display app.

If the framework determines that the consumer for the published Requested Delivery request is in a remote application, it uses the Remote component by inserting the message in the Transmit Queue.

Maintaining the Connections status for the communications with the Display has yet to be implemented.  The initial move of the display protocol to the framework retained the previous user component structure for Client and Response while adding the Method package to allow for different methods to be supported.  While doing the display communications monitoring the use of Remote Connections and common method packages will be examined. 


Protocols

With the move of the Display protocol to the framework it became necessary to be able to distinguish between the protocol that the framework previously implemented and the new one that it can also handle.  As well as the ability to designate other protocols in the future.  Therefore, as mentioned in the most recent previous post, the prior framework protocol will now be referred to as the Topic Protocol while the current protocol between the user apps and the display app will be referred to as the Display Protocol.  This is because it isn't really ARINC-661 and naming it the Display Protocol will allow a future implementation of ARINC-661 to be referred to as the ARINC-661 Protocol.

So now the framework supports Framework Topic protocol messages and Display protocol messages in a more or less common structure.


Tuesday, August 23, 2011

User / Display Application Generalization of Framework and Connection




User / Display Application Generalization of Framework and Connection


While implementing the ability of the framework to do the reconnect between User Applications when one "failed" (was closed) and then recovered (was reopened), I decided that this was something to also do between the Ada user application framework and the C# Display Application.  In thinking about that, I thought that I should first reorganize the Display App somewhat to make it more general; that is, to have the ability to support more than one communications method between the Display App and the User Apps, be able to support more than one Display App (or non-framework based app), and to have the framework support more than one communications protocol (in this case, move the user app / display app interface support from user components to the framework).

In addition, to support the reconnect monitoring, to have heartbeat messages as part of the communications protocol for the User App, Display App interface.
 


As part of moving the message support between the User Apps and the Display App from cloned user components (one such component for each User App interfacing to a display layer) to a supported communication protocol of the framework it became necessary to be able to differentiate between the framework inter user app supported protocol and the user app to display app protocol.

Since the communications between the user apps and the display app isn't actually ARINC 661, I decided to name it the Display Protocol and the topic based inter User App messaging the Topic Protocol. 

The ARINC 661 protocol specification, as updated in "ARINC 661-Supp 3-Adoption Draft1", adds an extended header.  This extended header allows some message verification that was previously missing.  I have added this extended header to the display event and command messages that I have been using up to now.  It contains a leading pair of bytes to identify the message block, the identifiers of the source and intended destination applications, the number of bytes that should be in the message, a health boolean that specifies the source application's determination of whether the destination application is executing correctly, and, among other fields, a message reference number to allow the destination application to check that the messages are received in order without drops.  Nothing for a CRC.

The A661 supplement 3 draft document states that messages can be sent with only the extended header.  Therefore, I will use that as the heartbeat message to be sent periodically between the two applications and used to monitor the communications bus.  This, has yet to be done.  It will be implemented along with the reconnect between the user application and the display app.
 

Display Application Structure

To allow for multiple communication methods and multiple protocols, the C# communication classes of the display application has been rearranged to mimic those of the user application framework.  That is, instead of just a MS_Pipe class to use Microsoft pipes to support the communications, there are now Remote and Method classes as well. 

The Method class is to select among the supported communication methods for those to be used between the display app and the destination app.  That is, like the user app, the communication methods supported by each application in the network is to be specified by a configuration file.  The Method class, as more methods are supported, will (as with the user apps) perform the communications with each supported method.  For now, Method only selects MS_Pipe as the only supported communications method but it is specified in a configuration file and has to be specified there.  As with the user apps, WinSock for instance, could also be supported or supported instead of MS Pipes and then Method would select the class that implements the new method.

The Remote class is the top level class as it is the top level package in the user app framework.  That is, an instance of it is invoked when a Windows control (widget) event is received.  It contains the common code to add the extended header to the event messages to be transmitted prior to invoking the Method class and to verify the received command messages.  Also like the framework package, it has the Watch function that will be used to monitor the message traffic and control reconnects.

Currently, Remote assumes that the Display protocol will be used so the Display extended header is what is added to messages to be transmitted.  If the supported protocol changes, this is where the change will be made.  Such as if the format of the message data becomes that of the A661 protocol.  Or if another type of application is implemented in C# that uses its own protocol.
 

Configuration File

A display configuration file has been added and the user apps configuration file has been extended.  Eventually these two files will be combined into a single file with multiple sections – to start with a User Application section and a Display Application section – but extendable to allow for additional types of applications in the network.

The display configuration file contains the display application identifier and name, the supported communication method(s), and is now where the display Definition File path is specified so it can be moved.  

In addition, both configuration files now contain the path to the application's executable so that the first application of the network that is running can cause the others to run.  At least those on the local PC and, I suppose, there must be a way to do this over the network as well.

A possible structure of a combined configuration file, might be as follows.  In such a structure, the data is organized into groups with possible multiple lines provided for each group.  Each line begins with the group identifier and the application identifier to which the group belongs.  For easier parsing, the data for a particular groups and applications are in consecutive lines.  Or, better yet, this data could be provided in XML.

In the following example of the possible structure, the Group Identifiers are APP, CM, and AP for Application data, for supported Communication Method data, and AP for Addition Protocol data.

In addition to the application id, the Application data provides the application name, the base protocol of the application (currently Topic or Display), the PC on which the application is located, and the path to the executable.  In addition, for the Display App, the path of the Definition File to be used is provided.

The supported Communication Method data depends upon the base protocol of the application to provide the data needed by that protocol.  Different data is provided for different communication methods.  For the MS Pipe communication method, no other data is provided since the Topic protocol between applications provides the algorithm for creating the MS Pipe names.  If the WinSock communication method is also supported by the application, the IP Address to be used is provided.

For the Display protocol, the MS Pipe communication method also provides the base portion of the pipe name for communication between the Display Application and the User Application for a particular Layer (1 and 2 for application id 15 in the example).  For a Topic Protocol application this data is provided by the Addition Protocol data lines that specify that the additional supported protocol is Display for connection with the application that has 15 as its identifier treating the events of display layer 1.  The example illustrates the future possibility of App 1 also using the Display protocol to connect with another application via a different communication method.

The configuration data for a particular application continues as long as its application id is provided.

+–-–+–-–+–
|Gp |App|
|Id | Id|
+–-–+–-–+–
|APP|  1|App 1|Topic|host PC|executable path|
+––-+–-–+–
| CM|  1|MSPipe|
+––-+–-–+–
| CM|  1|WinSock|IP Address|
+––-+–-–+–
| AP|  1|Display|15| 1|MSPipe|base pipe name|
+––-+–-–+–
| AP|  1|Display|Id|Layer|comm method|
+––-+–-–+–
|APP|  2|App 2|Topic|host PC|executable path|
+––-+–-–+–
| CM|  2|MSPipe|
+––-+–-–+–
| AP|  2|Display|15| 2|MSPipe|base pipe name|
+––-+–-–+–

  . . .

+–-–+–-–+–
|APP| 15|App 15|Display|host PC|definition file path|executable path|
+––-+–-–+–
| CM| 15| 1|MSPipe|base pipe name|
+––-+–-–+–
| CM| 15| 2|MSPipe|base pipe name|
+––-+–-–+–-+–––––-+–-

Note:  Currently, the Display App obtains the supported layers from the Definition File and the communication method and pipe/port name for the layer from the Definition File.  This could be another approach.  That is, in the Configuration File, provide the nodes of the network via the data of the APP group and includes a Definition File path for each User App as well as the Display App(s).  Then provide the communication methods, additional types of applications, etc in the specified Definition File.  Perhaps, also a list of each additional application to which a particular application should connect and use that to look up the base protocol of that application, its supported communication methods, etc via its entry in the configuration file.


Display Protocol in Framework

As part of the generalization of the inter app communications the interface with the Display App was moved from separate user components of App1 and App2 to the framework as a second supported protocol.  This will allow any user app to interface to the display app (or an additional display app) without the need to clone the previous component for the new application.  It will also allow the extension of the monitoring of the connection by the framework and the ability to reconnect as soon as possible.

For the initial shift of this functionality the Com_Display user component was just slightly reworked as the mC-Message-Display framework component with Method and MS_Pipe child packages.  This retains a structure that parallels that of the Remote package of the Topic protocol with the Method selector package and the MS_Pipe and WinSock communication method packages.  Retained are the Client and Response thread packages under the mC-Message-Display package where the retained Client corresponds to the various Receive threads of MS_Pipe and WinSock. 

Response is the thread that awaits responses from user components that register to treat various event messages.  It then translates the response to a Display protocol message, including the A661 extended header and transmits it to the display app.

Client awaits the Receive from Method that, in turn, awaits the receive from the display via the MS_Pipe interface acting as the client.  (The Display App is the server.)  The Method package can be extended to await the message receive of other display methods.  When this happens, a further reorganization will put the receive threads in the method packages with one receive thread for each display app to which the network might be extended.  That is, with multiple supported communication methods for the Display Protocol and/or multiple display apps configured into the network, the framework Display Protocol structure will need to be reworked again to be more similar to that of the Topic Protocol package structure. 

This initial move from individual user components to one framework component structured to retain as much code as possible was only to evaluate the problems that might arise.  The one that did – when App2 was also modified to use the framework – was that the two user components had each registered a different clone of the mT-Topic_Widget_Event_Layer and mT-Topic_Widget_Command_Layer topic (e.g., mT-Topic_Widget_Event_Layer1) when the second app's interface to the Display App was first implemented.  This was because there could be only one publisher of a One-of-N topic that is used to publish the event to deliver it to the requesting component and only one consumer of the response (the display command) topic.  Hence, two versions of the topic were needed.

Therefore, as a workaround, the mC-Message-Display was modified to select the version of these two topics that corresponded to the layer supported by the particular user application that was running.  This allows the received event message to be published and distributed to the user component that has registered to treat the event and for that user component to publish the command to be delivered to the new framework component of the application that treats the layer.  The Topic Widget Event message is a translation of the data of the received Display protocol message while the response Topic Widget Command will be translated by the mC-Message-Display-Response framework component to a Display Protocol message and transmitted to the Display Application using the connection for the layer.


Future Display Protocol in Framework

Although the above mentioned workaround satisfies the Topic protocol it is not an ideal solution since the addition of other layers would require further clones of the two topics and modification of the particular mC-Message-Display packages to select the correct Ada Topic package and topic Reader and Writer for the display layer.

The Remote framework component makes use of its being inside the framework.  When Register Topic messages are received they are evaluated as to whether they apply to the running application.  If so, the remotely supplied or consumed topic is registered by the Remote component.  Instances of such remotely registered topics are then accepted by the Remote Receive (acting as the consumer) and forwarded (acting as the publisher) – sort of an amplifier – to the topic consumer and any response is transmitted by Remote without using the normal notify mechanism back to the sender.  Something similar may be able to done for the widget event and command topics so that the topics are routed correctly without special versions of the topics now that the component is within the framework and has direct access to its private procedures.

Otherwise, there is the example of the Delivery Identifier message exchange delivery style where a delivery id is supplied.  This style is specified for the Widget Event topic where multiple user components can register to consume the topic but also supply the delivery ids that will be treated.  For the Widget Event topic the widget id is supplied as the delivery id and the framework only delivers the topic to the component that has registered to treat that particular delivery id.  This can be considered One-of-N in that there can be N consumers of the topic but only one can receive a particular instance of the topic – the one that registered to treat the delivery id.

In addition, there is the Request/Response message exchange delivery style that is N-to-One; that is, N possible producers but only one consumer.  In addition, the Response published by the consumer is only delivered by the framework to the component the published the request and only if it registered to consume the response.

Therefore, either a new message exchange style that combines these features could be created or the Delivery Identifier style could be extended to allow a response with that response delivered to the publisher of the request.

Either way, the Widget Event and Widget Command topics would be combined into a paired topic with a request (the display event) and a response (the display command).  The request would be delivered to the consumer that registered for the delivery (event) id and the response would be delivered to the component that published the request.  If an extension of the current Delivery Identifier delivery style is selected, then other topics of this style wouldn't be paired and there would continue to be no response to deliver.  This would be a One-of-N-to-One delivery style.

Another possible direction to follow is that developed for the Foreign language components that could register, through another private framework interface, their own version of an Ada topic.  It can be checked whether the topics would get delivered correctly if the Display component used the Foreign interface Register to register C versions of the two topics so that the Ada generic Topic Writer and Reader could be bypassed.

Display Communications Monitoring

Now that both the Display Application communications is in the Remote and associated classes and the User Application communications to the Display Application has been moved to within the framework, the Display Protocol communications can be monitored similarly to the Topic Protocol inter-application communications.  As well as attempts to reconnect after a loss of communications.

Currently the Display app only sends messages when a widget event occurs.  This won't be sufficient to recognize a continuing connection via the Watch procedure of the Remote class / package.  However, now that there can be the Extended Header-only message, it can be sent as a heartbeat message periodically by both the user app and the display app and the Watch procedure can monitor for an ever changing received message count.  If the count stays the same, it can declare a disconnect.

Likewise, a disconnect could also be declared for the MS Pipe class/package when the pipe interface recognizes the disconnect.  This can be signaled to the Watch procedure by the setting of a boolean in the class/package's Comm structure for the Watch procedure to monitor.

After a disconnect, the framework (and Display App) can attempt to get the pipe connected again. 


Other Associated Additions that could to be made

During my ARINC 661 work at an aerospace supplier, the user application was tracking changes to the display.  This would have allowed a certain amount of recovery if a temporary loss of communications (such as the display computer resetting) occurred.  The displays could have been restored to the last assumed display status (that is, to the state that they would have had if the last commands sent had been received and act on).  Or, to the state of the last saved checkpoint.

Some future addition to my exploratory project could retain some information about what was displayed to be able to recover somewhat from a disconnect.  Without this, the display can only redisplay the initial display after it begins execution once again.  (Of course, if the problem really is in the connection, the display will continue unchanged, except that it could display a Loss of Connection popup.)

Windows does some of this but not much.  That is, the desktop displays particular icons and toolbars upon each start and the like, but does not relaunch user applications that were running.  It now seems to relaunch Windows Explorer but only to display the startup page.  Particular applications such as Ultra Edit, if closed, will open the same files that were opened when the application was closed.  So certain applications have persistence to varying degrees.