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.
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.