3.2.  Asynchronous data transmission

An asynchronous data transmission involves a mechanism called a queue. In general, a queue is a service which temporarily holds messages destined for a receiving task until that task is ready to process them. The sending task passes messages off to the queue and does not wait for a response from the receiver. The queue guarantees that if it accepts a message then that message will be delivered. Cogent's asynchronous messaging is implemented through a queue administrator, called Cascade QueueServer, or qserve.

Asynchronous data transmission

Figure 3.2. Asynchronous data transmission

In the example above, when task 1 sends a message to task 2 it does so through the queue administrator. Task 1 transmits the message to the queue administrator, which replies immediately with an acknowledgment that it has held the message for delivery pending a request from task 2. Task 1 can now continue with its other duties without having to wait for task 2 to process the message.

The queue administrator then sends a signal to task 2 telling it that there is a message waiting for it in the queue. A signal is a special operating system mechanism that cannot block on another task and in this case acts like a flag to indicate to task 2 that there is a message waiting. This means that the queue program is never blocked waiting for a reply from a task that it has informed about a message waiting.

Task 2 sends a request for the waiting message and receives the data in a reply from the queue administrator.

It should be noted that the queue administrator never initiates a message transaction, and due to the nature of the send/receive/reply mechanism it will never block while transmitting a reply. Thus a queue administrator in this scenario will always be available to receive messages and the originator of an asynchronous message will never block.

There are a number of disadvantages to using asynchronous message passing. The sender and receiver in an asynchronous transaction must agree upon a queue name in order for the queue administrator to correctly route a message. This requires either hard-coded queue names, command-line arguments, or a queue-aware name server so tasks can discover the destination queue names. The Cascade DataHub uses a queue-aware name server called nserve to provide maximum flexibility in asynchronous connections.

A second concern is that because asynchronous transmission introduces additional message passing overhead into the transmission mechanism, the speed of asynchronous transmission will tend to be slower than that of synchronous data transfer. Perhaps the biggest drawback of the asynchronous transmission method is that there must be a method of dealing with overflows in the queue. If the receiving task fails to collect its messages from the queue administrator, or if it cannot keep up with the rate at which messages are being sent to the queue administrator, then eventually messages will build up and the queue administrator will run out of buffer space. At this point, the queue administrator must refuse further incoming messages until the receiver has cleared some of its pending messages. The sending task must include a contingency plan for undeliverable messages.

A sending task may react in several ways to a full queue situation:

    Throw away data that cannot be put on the queue.  This is both the most common and least acceptable response to a full queue. The most recent data will be lost, and old data currently on the queue will be retained. Once the condition causing the full queue has been cleared, the most recent data will be unavailable. In the case of process control systems, this scenario will fail to transmit the most recent process changes. Obviously, this method is not attractive when you consider the potential loss of state change information and critical alarm data.

    Throw away the oldest data on the queue.  This method is only viable if the queue is held internally to the sending task. In most cases, a task cannot walk the queue as it is provided by an external program or operating system facility. Even if the queue is available to the sender, there is no guarantee that the oldest data is the least important. In general, eliminating data solely on the basis of age is unacceptable. (In the case of the QNX queue administrator, Mqueue, this method of dealing with a full queue is not an option, as the queue is held externally to the sender.)

    Throw away the oldest duplicate data on the queue.  As above, this option is only available if the queue is internal to the sender. In addition, it implies that the data in the queue is of a known type and format, and can be examined for its similarity to new data. In the case of process control points, this is generally true, though it means that every point being transmitted must be compared to every queued message to determine whether it should replace a current message or go to the end of the queue. Depending on the implementation, this mechanism may not preserve time ordering in the queued data. The Cascade DataHub uses a generalized external queue mechanism, and so does not provide this type of data reduction.

    Try to send the data again later.  If a task cannot deliver a message to the queue immediately, then it has the option of holding the message for later transmission. Once space is available in the queue, the message can be re-transmitted. This method actually means that the sender is implementing its own internal queue, duplicating the work of the queue facility, and so is subject to all of the same concerns regarding full buffers and data reduction. In general, this approach by itself is entirely useless, and is exactly equivalent to enlarging the size of the queue administrator's buffers. When used in combination with one of the other methods mentioned here, this approach could be very effective.

    Try to send the data again later, throwing away old duplicate data from the retry queue only.  This is the method used by the Cascade DataHub to deal with undeliverable data. So long as the receiver is capable of keeping up with the data transmission rate, all point changes are deliverable. If the receiver allows its queue to fill, then the Cascade DataHub will flag the point as pending delivery to the recipient and will attempt to deliver the most recent value for that point as soon as there is room in the queue. If another change to a pending point is received by the DataHub, then the previous value is overwritten, so that when room in the queue becomes available, the new value is transmitted. In addition, the Cascade DataHub packages many point changes into a single message whenever there are several pending points to a task, thereby increasing the bandwidth of the queue administrator during periods of high load. In this way, the Cascade DataHub will transmit all point changes to any receiver that can handle the data rate, and guarantees that even slow receivers (such as GUI applications and applications on dial-up lines) will always receive the most recent point values even if they miss some intermediate values.