Tuesday, May 28, 2013

External Components – Database Query Implementation Update

External Components – Database Query Implementation Update

Background:

As mentioned in the last post, my Framework and database interface component were unable to handle the publish and delivery of a query response when the database interface component sent a database query to the external database component/application process.  The publish of the query response was successful but its delivery back to the requesting component failed.

At the time I thought it was because the request topic message had been released when the database interface component returned control to the Framework after sending the query to the external database component/application.  Therefore, I added code to the Framework to detect that the requesting component had subscribed for a response but that the response had yet to be published.  This to avoid releasing the request too soon.

This required a number of changes to keep track of components that subscribed for a response versus those that hadn’t and set when the response was published so that the release code could avoid the release when the response had yet to be published.

Before I had finished with these changes I recognized that they were not going to provide the solution.

That is, first of all, the fact that the request had been released was not the reason that the Framework lacked the ability to determine which component was the requestor.  This had been based upon the consumer of the request producing and publishing the response before returning to the Framework.  Therefore, when published, the Framework could determine the publisher of the last request topic message that it had delivered to the consumer.  And hence could forward the response to it when it was published.

Prior to the publish of the delayed response, the consumer component had been activated once again by the publish of the wakeup topic by the Named Pipe Receive component as it queued the received response message from the external database.  Since the receive thread is really a subcomponent of the database interface component (that is, DBI1 – see diagram of the April 29 post "External Components – Database Queries") the producer of this request message is the same as the consumer.  Therefore, the Framework in checking the producer of the last request that activated the consumer component, no longer was able to determine the producer of the original query request.

To solve this problem while allowing delayed responses (that is, responses that are published after the consumer component has returned control to the framework following receipt of the request) would require further changes.

And, to complicate matters further, multiple request producers are allowed.  Therefore, a number of requestors could concurrently publish a request.  With immediate response the framework, via the framework component Scheduler, queues these requests to the run queue for the thread priority of the consumer component.  When the consumer returns to the framework, the Scheduler activates the message topic callback of the next component in the particular run queue.  Therefore, if multiple requestors concurrently published request topics, the other requestors would have their requests in the queue and the consumer component would be immediately reactivated to treat the next request in the queue and the framework would save this requestor as the one to which to return a response.

If delayed responses were to become allowed, the framework would deliver the next request before the response to the previous request had been received by the DBI1 component (acting as the middle man between the requesting component and the external database component).  This new query could then be sent to the external database component or it would be necessary to queue it in the DBI1 component.  If allowed to be sent to the external database component it might interfere with the previous query or be for a different database.  If for a different database, that database might provide faster results than that of the previous query causing its response to be returned to the receive queue before that of the first query.  Then the responses would be published out of order of the requests requiring further solutions to be developed.

Better to change the framework to avoid selecting the next request topic of the run queue until the delayed response is published.  This would continue to keep track of all the requestors that had concurrently published by the existing mechanism – as changed to wait until the response was published.

Before I thought of the above possibility as a fix, a different solution occurred to me and I decided to implement it.  I completed and retained the delayed response changes that I had already made in case I might continue with them later.  That is, those changes that would avoid the release of the request until the response was published which would prevent the requestor from writing and publishing a new request until its previous request had completed.

It’s well that I did since further reflection reveals that such a change wouldn’t have worked anyway.  That is, a change to avoid examining the run queue until the response was sent would also prevent the receive of the Read the Receive Queue wakeup event.

The Alternative Solution:

In the alternative solution the Database Interface component has another subcomponent in addition to the instantiation of the Named Pipe Receive thread.  This additional subcomponent is the thread that communicates with the external database component while the main component thread waits for the query response so that the query response can be interpreted and published as the response to the request topic.  The main component is the one that subscribes to consume the requests and publishes the responses to be returned to the requesting component by the framework. That is, it is the interface to the requesting components. 

Since the main component waits for the completion of the query, the publish of the delayed response acts the same as an immediately published response to the framework.  That is, it doesn’t exit back to the framework until after it has published the response. 

Therefore, any concurrent requests by other requesting components remain in the Scheduler run queue of the thread priority level.  And the component that made the request (along with those that made the queued concurrent requests) cannot use the request buffer to write and publish a new request.

It’s just that the main component becomes a long duration component the same as if it had complicated time-consuming computations to perform.

I implemented this as in the following diagram.

    +––––-––––-––––-––––--+ 
    |                     |
    |      Framework      |
    |                     |
    +––––-––––-––––-––––--+ 
               Λ         \
               |          \
  +-–––––––––––|–––––––––––\––––--–––––––––––––––––––––––-–––––––-+
  |            |            \    DBI1 Package/Component           |
  |            |             \                                    |
  |            V              \                                   |
  |   +----–––––––----–––-+    V+----–––––––----––-+              |
  |   |      Message      |     |     Database     |              |
  |   |      Portal       |     |     Manager      |  +––––––––-  |
  |   |       sub         |     |       sub        |  | Receive   |
  |   |     component     |     |     component    |  |  Queue    |
  |   |             /---\ |     |                  |  +––––––––-  |
  |   |             | P |<-–\   |                  |      Λ       |
  |   |             \––-/ |  ––-|                  |      |       |
  |   +----–––––––----–––-+  C  +----–––––––----––-+     /        |
  |                                          |          /         |
  |                                          |         /          |
  +-––––––––––––––––––––––––––––--–––––––––––|––––––––/––––––––-–-+
                                             |       /
         P = Pause                           V      /
         C = Continue event             +––––-––––-–––––-+
                                        |    External    |
                                        |    Database    |
                                        |    component   |
                                        |                |
                                        +––––-––––-–––––-+

In the diagram the main component is called the Message Portal subcomponent while the subcomponent that communicates with the External Database component is the Database Manager subcomponent.  (Architecture-wise, the main component is just the initially registered component that is assigned the initial component key.)

The main component was named the Message Portal since it is the subcomponent to subscribe to consume the message request topics that the Database Interface Ada package (C++/C# class) treats and then to publish the response to be delivered back to the requesting component.

The Database Manager subcomponent is the one that manages the databases and communicates with the External Database component.  It is the subcomponent that tracks when both the connection to the named pipe has occurred and when power up processing has completed such that queries can be sent to access the database.  Eventually it will also monitor the External Database component, receive notifications when a connection between the External Database component and a particular database has been completed or lost, and send commands to establish such a connection or close it.

As such, as illustrated in the diagram, it also has an interface to the framework to receive instances of topics such as power up complete or a periodic wakeup to perform monitoring.  Likewise, to receive the wakeup that indicates that a message from the External Database component has been received and queued.  But, to avoid the delayed response problem, it must not subscribe to treat query requests or any other request that needs a response unless it can publish an immediate response (– meaning before the callback returns to the framework).

The Message Portal is activated by the framework when it is able to deliver a query request of another component.  The Message Portal will then interpret the request topic and form a query message formatted correctly for the particular database that will obtain the data from which a response can be created.  It then buffers the query message, sends a wakeup message to the Database Manager subcomponent and enters its Pause to await the response. 

The Database Manager is run by the framework via the callback for the particular wakeup topic and then retrieves the query message and transmits it to the External Database component via the named pipe that will cause the particular database to be accessed that will obtain the response.  When the External Database transmits the response the External Pipe receives it, queues it, and sends a read the queue wakeup request to the framework.  The framework than causes the Database Manager to run via its callback for this topic and the Database Manager buffers the response and signals the Message Portal to Continue.

The Message Portal then retrieves the buffered query response and extracts the necessary data to publish the response to the original request.  Upon doing the Publish the callback procedure for the original request returns to the framework completing the processing of the request.

Instead of the Message Portal buffering the query message for retrieval by the Database Manager, the interface between them could be to publish a query request topic message for which the Database Manager would subscribe to consume (as long as no response is involved).  However, the response still must be buffered for retrieval by the Message Portal since it is waiting for the response to be ready as it cannot receive a wakeup message.  The ability to react to a wakeup message would revert to the original problem.  Therefore, for symmetry, I buffered both the query and the query response for retrieval by the opposite subcomponent.

The two messages can be buffered since only one request will be treated at a time.  Therefore, the access of the buffer is thread safe since the Message Portal will buffer the query message and then wake the Database Manager to treat it.  Likewise, the Database Manager will buffer the query response and then signal the Message Portal subcomponent to treat it.  Neither will use the buffers again until the next request is received by the Message Portal.

Unexpected Problem:

In my initial implementation to try this idea, the Message Portal did the Pause as a delay loop using the Ada delay statement while checking a Continue boolean as the signal to exit the delay loop.  Although I didn’t intend to retain this mechanism it worked as anticipated and was thread safe since a unary object was being monitored and set. 

However an unexpected problem occurred when the Message Portal received the request topic and sent the wakeup to the Database Manager.  The Database Manager didn’t run.

Luckily I soon thought of the reason.  Deadlock. 

The two subcomponents had been registered with the same expected time interval for processing.  Therefore, their threads were assigned to the same priority level and to the same Scheduler run queue.  Because of this the wakeup for the Database Manager subcomponent was added to the run queue behind the request that was being treated by the Message Portal subcomponent.  As such it would stay there until the Message Portal returned control to the framework.  Which it wasn’t going to do until it was informed that the query response was ready for interpretation.

The problem occurred since the Message Portal should have been assigned a longer expected time interval for processing.  Although it can handle its interpretation of the request quickly enough it is going to wait until the External Database component receives the query message, presents the query to the database, and the response is transmitted back to the Database Manager subcomponent.  Therefore, the Message Portal subcomponent needed to be assigned to a longer duration thread and the topic message to its associated run queue.

With this fix everything worked fine.

Subcomponent Pause Resources:

The next modification was to implement a Pause/Continue resource similar to a semaphore for use by subcomponents. 

Components can only communicate with each other via the framework topics where one component can signal any other component that’s interested (that is, has subscribed to consume the particular topic) that there is new data to be read.  Or the consuming component can just read the latest values whenever it runs.

To retain this component independence a Pause/Continue resource was added where a particular resource can only exist for use by the subcomponents of a component. 

To implement this resource the registration of components was adjusted such that a subcomponent can supply the key of the previously registered component/subcomponent so that all the fields of the private key began to be used.  This allowed the recognition of a subcomponent group by the framework while assigning a unique key to each subcomponent.

Then a new register interface was added to request a Pause/Continue resource be assigned by supplying the component key.  The Pause and Continue interfaces are supplied the resource key which, by programming convention, is to be privately retained within the Ada package body similar to the private code of a C++ or C# class.  The framework checks that the key supplied to create the resource refers to a component and that the resource key used by a Pause or Continue request is for a subcomponent of the component that owns the resource.  Therefore, subcomponents can signal each other within a component but not other components.

Otherwise, the Pause/Continue resource is just another event as far as the framework is concerned and so was simple to implement.

The implementation allows multiple resources to be assigned to a component since more than one subcomponent might need to Pause.  Also, a resource kind was specified so that other kinds of resources can be added in the future if warranted.  

The Pause/Continue resource allowed me to replace the Ada delay loop with the invocation of a Pause and the Database Manager to signal that the query response was available by invoking the Continue.

Finishing Up:

Because of these problems I also recognized that long duration upon demand components could block each other if assigned to the same thread priority run queue.  To prevent this from happening (so that they would have to share computer execution by round robin or other means of the operating system) I modified the allocation of run queues such that only short duration components could be assigned to a shared run queue.  Therefore, upon demand (that is, event driven) long duration components will run, except for how initiated, the same as aperiodic and pseudo periodic components.




Wednesday, May 15, 2013

External Components – Database Query Implementation



Database Application:

The C# program to access databases has been created as pretty much a clone of parts of the display app.  That is, it uses modifications of the display code
A) to read the configuration file and load and run its paired Ada application,
B) use MS_Pipe named pipe threads to communicate with the paired application for each database to be supported,
C) create a specific thread for each supported database to interface with the database,
D) an instance of a queue for each database into which to add received query messages.

As with the display app, the database app periodically wakes up each of the database access threads.  When awoken these threads check their queue to determine if it has any entries received from a user app.  If so, it dequeues the query message and acts on it and then causes the data retrieved from the database to be transmitted to the user application that sent the query.

Further development is needed to add commands such as Open and notifications to the user app such as the database is not connected or has become disconnected.  That is to have the Database Interface component control the opening of the database in a manner similar to the A661 user app controlling the enabling of a layer and being notified when the layer becomes inactive.

Database Interface Component:

The very basics of the Database Interface component of the user application has been created in order to check the ability of the user application's components to publish framework topics that the Database Interface Component (see diagram of the April 29 post "External Components – Database Queries") then consumes.

Generalized features such as those intended for the Schema package of the diagram have yet to be worked upon.  That is, there is nothing as yet to read the schemas for various databases and associate potential queries and database updates with particular interpretation procedures to translate a received topic to a query to be transmitted to a particular database and to translate the response from the database to the response topic to be returned to the requesting component.

Only the minimum has been done to check whether a user component can publish a topic that the DBI1 database interface component subscribes to consume.  This minimum to check that when a topic is received by the database interface component that it can then create and transmit an associated query, get the query response, and then send a topic response back to the requesting user component.

With this sample topic/query treatment the database interface component checks whether its connection to the external database application has been made so that the query can be sent.  If not, it sends a response back to the requesting component that the request wasn't honored.  Otherwise, it creates the query and transmits it to the database app.  When the response is received, it is placed into the received message queue of the database interface component and a wakeup event for the component is sent to the framework.  The database interface component is than run by the framework and it retrieves the query response from the queue and creates the response to return to the requesting component.

Detected Framework Insufficiency:

Before the connection to the external database application occurs the database interface component creates the not handled response and publishes it.  The requesting component then is run by the framework and it gets the response topic.

After the connection to the external database application occurs the database interface component creates and transmits the query.  It then receives the response from the database application via the Receive thread of the instantiation of the generic MS_Pipe package and creates and publishes the response topic. 

The newly detected framework problem is that this response topic is not delivered to the requesting component.

After trying for a while to determine the reason for this, it has occurred to me that it is because the Request/Response message exchange method was implemented with the expectation that the response would be published before the request consumer component returned to the framework after being notified of the request.

The framework then delivers the response and the topics are released.  Since it isn't necessary for the requesting component to subscribe for the response, the framework can ignore the published response rather than attempt to deliver it when the requesting component didn't subscribe for it.  Therefore, the topics are released without regard to whether the response was delivered. 

At least I think that is what is happening.  Therefore, I will change the release to avoid releasing the request if the requesting component subscribed for a response but the response has yet to be published. 

This should be easy enough since I already have code to detect whether the requesting component subscribed for a response.  So all that will be necessary is to do the same check for the release as well as a new check for whether the response has been published.  Where an additional problem may arise is to keep doing attempts to do the release until the response has been published and delivered.

Therefore, these changes will be made to the framework before generalizing the database interface and making the additions to the database application.