Return to ING home page4.1 Implementation of DRAMA actions

This page is part of the ING document INS-DAS-31 Design notes for UltraDAS

Action tables; obey handlers

The mapping of DRAMA obey commands to callbacks is set by the table actions_pt_1 in the Camera-facade class. This is a standard table of type DitsActionDetailsType, as used in most DRAMA servers. All the callbacks are private methods inside Camera-facade.  Most of the actions, and almost all the ones used in normal operation have obey as the obey handler and kick as the kick handler. The exceptions to this rule are the actions that operate entirely in the scope of the DRAMA thread, such as PING, RESET and EXIT; these have specialised obey handlers and no kick handlers.

Actions handled by obey have two phases: phase 0 at invocation and phase 1 at the end of the action. The obey method calls obey_0 for phase 0 and obey_1 for phase 1. The obey_0 method creates an action thread to execute the action; obey_1 recovers (i.e. joins with) the action thread.

The table actions_pt_2, also private to the Camera-facade, specifies which private method of the class should be run in the action thread. This table is a local mechanism of udas_camera and is nothing to do with the DRAMA libraries. The table contains addresses of action methods to be executed.

The tables actions_pt_1 and actions_pt_2 are both indexed by the array action_codes, which is an enumeration of symbolic codes for the actions. Values from action_codes are set into actions_pt_1 such that they can be retrieved by a call to DitsGetcode, and then used as an index into actions_pt_2 to fetch the address of the method needed to execute the action. Clearly, alterations to action_codes, actions_pt_1 and actions_pt_2 need to be coordinated to preserve the indexing.

Action objects

The callback  method obey_0 prepares and Action object to describe the context of the action; the object is a convenient way to pass the context to an action thread. Action objects aren't first-class objects in the way that Camera-facade and, e.g., Shutter are; they are only used inside Camera-facade and are not implemented as a full class.

An action object records the identifier for the thread doing the action, the (DRAMA) name of the action, the index of the action (needed for signaling back to the DRAMA thread) and any Exception arising during the action.

Action objects follow the planned family pattern. There is on Action for each DRAMA action, and the objects are reused (with appropriate reinitialisation) in successive invocations of an action.
 

Thread handling; kick handlers

The obey_0 method starts an action thread for its action; the obey_1 method joins with that method when the action is over. Figure 4.1.1 shows the time-line for the thread.


Figure 4.1.1: life-cycle for an action thread.

The thread is started with a specific set of Pthreads attributes that are common to all action threads. The Camera-facade creates the attribute object at construction and uses it each time a thread is started. If a new set of attributes were used for each thread, the attributes object would be leaked, as libpthread doesn't manage these objects. The attributes imposed system-scope scheduling on the thread such that it is bound to a light-weight process in the kernel and is scheduled by the kernel instead of by libpthread. Kernel scheduling is less efficient, in that context switching takes longer, but scheduling by libpthread is ineffective, in that the DRAMA thread is starved of CPU and reacts too late to some events.

All the action threads are started in the method Camera_facade::do_action. That method then calls the action method named in the Action object and blocks, waiting for the action method to return. After the action method returns, do_action calls DitsSignalByIndex, and returns. That sequence causes the DRAMA thread to reschedule the action, to call obey_1 and hence to join with the action thread.

When an action is kicked, the kick handler kick cancels the action thread. It gets the identifier of the thread from the action object and calls pthread_cancel. The kick handler then returns, causing the obey handler to be scheduled again, which in turn causes the cancelled thread to be joined.

Action methods

Inside Camera-facade, there is a private method for each action. These methods are named xxx_action, e.g. run_action, readout_action etc. The action methods run in the action thread and implement the action as a sequence of calls on other objects. In most cases, the entire action can be delegated as a call to one method on one external object; this is the ideal. In a few cases, the Facade follows the bridge pattern and makes simple calls to two or more objects that aren't designed to communicate directly; this is also good practice. In a very few cases, notable for the GRAB and CDS actions, the Facade has to make a complex series of calls to actions, such that a significant part of the logic of the action appears in the Facade; this is done reluctantly, where circumstances force it.

At no point does an action method start a new thread. If a worker thread is needed, it is started by one of the objects that the action method calls. (See particularly the Run class.)

Argument passing

Arguments of the DRAMA actions come in to the Facade as SDS argument lists. These are extracted by the obey_0 method and repacked as members of an arguments C-structure that is in turn part of the Action object. The action methods get the arguments by reading the sub-structures of the Action objects. Return arguments (only a few action have these) use the argument mechanism in reverse. Action methods set fields in the argument sub-structures of the Action objects; the obey_1 method unpacks the Action objects and forwards the arguments as entries in an SDS argument list; the argument list is sent back to the client with the final message of the obey transaction.

The action-argument structure has a field for every possible argument of all the actions. Most of the fields are unused in most cases.

Error reporting

Errors occurring during an action are reported by the action method attaching an Exception object to the Action object. When there is no error, the Action object comes back with a null pointer in the field for the Exception.