This version is identical to V1.0RC2.
NOTICE FOR FUTURE RELEASES: AVOID CHANGING THE NUMBERING! The tests refer to the sections, incl. links and unlinked references from tests or other parts of the specification. These break, or even worse become wrong, when they are not changed consistenty!
1. General idea
- 1.1 In ApplicationCore each variable has a data validiy flag attached to it. DataValidity can be 'ok' or 'faulty'. [No explicit test]
- 1.2 This flag is automatically propagated: If any of the inputs of an ApplicationModule is faulty, the data validity of the module becomes faulty, which means all outputs of this module will automatically be flagged as faulty. [T] Fan-outs might be special cases (see 2.4).
- 1.3 If a device is in error state, all variables which are read from it shall be marked as 'faulty'. This flag is then propagated through all the modules (via 1.2) so it shows up in the control system. [T]
- 1.4 The user code has the possibility to query the data validity of the module [No explicit test]
- 1.5 The user code has the possibility to set the data validity of the module to 'faulty'. However, the user code cannot actively set the module to 'ok' if any of the module inputs are 'faulty'. [No explicit test]
- 1.6 The user code can flag individual outputs as bad. However, the user code cannot actively set an output to 'ok' if the data validity of the module is 'faulty'. (*) [T]
- 1.7 The user code can get the data validity flag of individual inputs and take special actions. [No explicit test]
- 1.8 The data validity of receiving variables is set to 'faulty' on construction. Like this, data is marked as faulty as long as no sensible initial values have been propagated. [T]
Comments
- 1.6: The alternative implementation to add a data validity flag to the write() function is not a good solution because it does not work with writeAll().
2. Technical implementation
2.1 MetaDataPropagatingRegisterDecorator (*)
- 2.1.1 Each input and each output of a module (or fan out) is decorated with a MetaDataPropagatingRegisterDecorator (except for the TriggerFanOut, see. 2.4) [T]
- 2.1.2 The decorator knows about the module it is connected to. It is called the 'owner'. [No explicit test]
- 2.1.3 read: For each read operation it checks the incoming data validity and increases/decreases the data fault counter of the owner. [T]
- 2.1.5 write: When writing, the decorator is checking the validity of the owner and the individual flag of the output set by the user. Only if both are 'ok' the output validity is 'ok', otherwise the outgoing data is send as 'faulty'. [T]
2.2 removed
2.3 ApplicationModule
2.4 TriggerFanOut
The TriggerFanOut is special in the sense that it does not compute anything, but reads multiple independent poll-type inputs when a trigger arrives, and pushes them out. In contrast to an ApplicationModule or one of the data fan-outs, their data validities are not connected.
- 2.4.1 Only the push-type trigger input of the TriggerFanOut is equiped with a MetaDataPropagatingRegisterDecorator. [T]
- 2.4.2 The poll-type data inputs do not have a MetaDataPropagatingRegisterDecorator. (*).[No explicit test]
- 2.4.3 The individual poll-type inputs propagate the data validity flag only to the corresponding outputs. [T]
- 2.4.4 Although the trigger conceptually has data type 'void', it can also be
faulty
(*). An invalid trigger is processed, but all read out data is flagged as faulty
. [T]
2.5 Interaction with exception handling
See Technical specification: Exception handling for device runtime errors V1.0.
2.6 Application class
- 2.6.1 For device variables, the requirement of setting receiving endpoints to 'faulty' on construction can not be fulfilled. In DeviceAccess the accessors are bidirectional and provide no possibility to distinguish sender and receiver. Instead, the validity is set right after construction in Application::createDeviceVariable() for receivers.
Comments:
- 2.1 The MetaDataPropagatingRegisterDecorator also propagates the version number, not only the data validity flag. Hence it's not called DataValidityPropagatingRegisterDecorator.
- 2.3.3 If a module has an output that would still be valid, even though one of the inputs is faulty, it means that the output is not connected to that particular input. This is an indicator that the module is doing unrelated things and probably should be split.
- 2.3.3 A change of the data validity of the module does not automatically change the validity on all outputs. A module might not always write all of its outputs. If the module's data validity is 'faulty', those outputs which are not written stay valid. This is correct because their calculation was not affected by the faulty data yet. And if an output which has faulty data is not updated when the data validity goes back to 'ok' it also stays 'faulty', which is correct as well.
- 2.4.2 The data validities of the different poll type inputs are not correlated, so they shall not be propagated to the TriggerFanOuts data fault counter. The version numbers of poll-type inputs are not propagated anyway, so there is nothing for the decorator to do.
- 2.4.4 A void variable can be invalid if the sending device fails, hence there is no new data, and then a heartbeat times out and raises an exception. This will result in a void variable with data validity
faulty
because it does not originate form a recevied message.
3. Implementation details
- 3.1 The decorators which manipulate the data fault counter are responsible for counting up and down in pairs, such that the counter goes back to 0 if all data is ok, and never becomes negative. [No explicit test]
4. Circular dependencies
If modules have circular dependencies, the algorithm described in section 1 leads to a self-excited loop: Once the DataValidity::invalid flag has made a full circle, there is always at least on input with invalid data in each module and you can't get rid of it any more. To break this circle, the following additional behaviour is implemented:
4.1 General behaviour
- 4.1.1 Inputs which are part of a circular dependency are marked as circular input.[T]
- 4.1.1.1 Inputs which are coming from other applicatiation modules which are not part of the circle, from the control system module or from device modules are considered external inputs.[T (only CS module)]
- 4.1.2 All modules which have a circular dependency form a circular network.[T]
- 4.1.2.1 Also entangled circles of different variables which intersect in some of the modules are part of the same circular network.[T]
- 4.1.2.2 There can be multiple disconnected circular networks in an application.[T]
- 4.1.3 Circular inputs and circular networks are identified at application start after the variable networks are established.
- 4.1.4 As long as at least one external input of any module in the circular network is invalid, the invalidity flag is propagated as described in 1. [T]
- 4.1.5 If and only if all external inputs of one circular network are back to DataValidity::ok, all circular inputs of the circular network ignore the invalid flag and also switch to DataValidity::ok. This breaks the self-exciting loop.(*) [T] [T] [T]
- 4.1.6 If all inputs of a module have DataValidity::ok, the module's output validity is also DataValidity::ok, even if other modules in the circular network have external inputs which are invalid.
- 4.1.7 Control system variables and device registers are never part of a circular dependency.[T (CS variables)] [T (Device variables)]
- 4.1.8 If the user code of a module progammatically sets one of its outpts to
faulty
, this is treated as if an external input was invalid.[T]
Comments
- 4.1.5 In principle the data validity is always set to
ok
"too early" because the data content at the circular inputs is based on invalid data. If it is strictly required that a DataValidity::faulty flag is always transported correclty because critical decisions depend on it, circular dependencies must be avoided in the application.
4.3 Technical implementation
- 4.3.1 In addition to the owner (see 2.3.1), the circular network (4.1.2) also gets an atomic invalidity counter.(*).
- 4.3.2 Each module and each circular input knows its circular network [T]
- 4.3.3 If an external input receives data, it increases/decreases the circular network's invalidity counter, together with the owner's invaliditys counter.
- 4.3.4 If a module estimates its validity (as used in 2.1.5), it returns
DataValidity::ok
if the module's internal invalidity counter is 0 (4.1.6)
DataValidity::ok
if the module's internal invalidity counter is not 0 and the circular network's invalidity counter is 0 (4.1.5)
DataValidity::faulty
if both counters are not 0 (4.1.4)
Comments
- 4.3.1 This counter has to be atomic because it is accessed from different module threads.