sequence

Name

sequence -- States, Sequence, Transitions API

Synopsis


package require sequence

sequence::newState db state-name
sequence::newTransition db from to
sequence::add db sequence-name trigger
set stepno [sequence::addStep db seqname program predelay postdelay]
sequence::rmvstep db name stepno
set stepno [sequence::insertStep db seqname program priorstepno predelay postdelay]
set stepno [sequence::prependStep db seqname program predelay postdelay]
sequence::rmvState db state-name
sequence::rmvSequence db name
sequence::reachable db state-name
sequence::listReachableStates db state-name
sequence::listLegalFromStates db state-name
sequence::listStates db
sequence::listLegalNextStates db
sequence::isLegalTransition db next
sequence::currentState db
sequence::listSequences db
sequence::listSteps db sequence-name
sequence::addMonitor db sequence stepno monitor-base-command
sequence::runSequence db name ?endproc?
sequence::transition db transition ?endscript?
sequence::getCurrentTransition
sequence::relayOutput text


      

DESCRIPTION

This package provides several facilities:

EXPORTED ENTRY POINTS

In the entry points below the formal arguments named db are always an sqlite3 database connection command that designates the database that will be operated on.

sequence::newState db state-name

Defines a new state in the state machine. The new state definition is stored in the configuration database connecected to the sqlite3 command db. The new state will be named by the new-state parameter. The new state name must be unique.

Note that unless transitions into this state are defined, the state remains an orphan in the state diagram, in the sense that it cannot be reached via state transition operations. See ::sequence::newTransition below.

sequence::newTransition db from to

Defines a new state transition in the database connected to db. The transtion is defined between the named states from as a precursor and to as a successor.

Both the from and to states must already be defined.

sequence::add db sequence-name trigger

Defines a new sequence in the database connected to db. The sequence will be named sequence-name which must not yet be the name of a sequence. The steps in the sequence will be triggered by a transition into the state named by the trigger.

Initially the sequence is empty and will do nothing if triggered. sequence::addStep and other sequence step editing commands are used to define the steps in a sequence and their order.

sequence::addStep db seqname program ?predelay? ?postdelay?

Adds a new step to the end of the sequence seqname. The step will run the program named progname. The optional predelay and postdelay parameters are a delay in seconds before and after executing the step. These default to 0 if not specified.

The return value of this command is the step number that was assigned to the step. Step numbers are real numbers and are used to ensure steps are executed in the correct order. Real values are used to allow steps to be inserted between existing steps without needing to renumber the entire sequence.

sequence::rmvstep db name stepno

Removes the step numbered stepno from the sequence named by name.

sequence::insertStep db seqname program priorstepno ?predelay? ?postdelay?

Inserts a new sequence step after the existing step with a step numbered priorstepno. The remaining parameters are the same as the parameters for ::sequence::insertStep.

Naturally if priorstepno designates the last step in seqname, this command acts identically to ::sequence::addStep.

The command returns the number of the new step.

sequence::prependStep db seqname program ?predelay? >postdelay?

Adds a new first step to the beginning of seqname All the remaining parameters are the same as ::sequence::addStep. The command returns the number of the new step.

sequence::rmvState db state-name

Removes the state state-name from the state machine definition. This can have far reaching consequences so use with care:

  • All sequences triggered by entry to this state are removed along with all steps in those sequences.

  • Depending on the actual graph of the state machine, this may leave the system with unreachable states.

  • Depending on the current state of the system, this may leave the system in a state with no valid successor states.

sequence::rmvSequence db name

Removes the definition of the sequence name. Note that all steps in the sequence are also removed from the database.

sequence::reachable db state-name

Returns the number of valid precursor states to the state state-name. A precursor state is a state that has a transition to state-name defined. If the returned value is 0, state-name is orphaned in the sense that there it cannot be reached from any other state in the state machine via a legal transition.

sequence::listReachableStates db state-name

Returns a list of the states that can be reached by transition from the state state-name.

sequence::listLegalFromStates db state-name

Returns a list of state names that can transition to state-name.

sequence::listStates db

Lists all the states defined in the system. Using this and sequence::listReachableStates as well as sequence::listLegalFromStates it is possible to programmtically reconstruct the full state diagram.

sequence::listLegalNextStates db

Returns a list of states that can be transitioned to from the current state. Note that the system's current state is stored in the database.

sequence::isLegalTransition db next

Returns a boolean that is true valued if next is a legal next state for the current state. This is a shortcut for expr $next in [::sequence::listLegalNextStates].

sequence::currentState db

Returns the name of the current state.

sequence::listSequences db

Returns a list of dicts that describe the currently defined set of sequences. The key/values in this dict are:

id

Integer primary key of the sequence.

name

Name of the sequence.

transtion_name

Name of the state whose that triggers the execution of the sequence. An attempted legal transition to this named state will trigger sequence execution.

transition_id

The primary key of the transition named in transition_name.

sequence::listSteps db sequence-name

Returns a list of dicts that describe the steps in the sequence named by sequence-name. Each of these dicts has the following key/value pairs:

step

Real number that is the step number of that step. Steps are executed from lowest step number to highest step number.

program_name

Name of the program to run when the step is executed.

program_id

Primary key of the program to run when the step is executed.

predelay

Number of seconds to delay prior to running the program (integer).

postdelay

Number of seconds to delay after running the program (integer).

sequence::addMonitor db sequence stepno monitor-base-command

Attaches an output monitor to a step in a sequence. The name of the sequence is sequence. The monitor is attached to step stepno. monitor-base-command is the base command of a command ensemble described in OUTPUT MONITOR OBJECTS that is the output monitor for the program in that step.

sequence::runSequence db name ?endproc?

Runs the named sequence name. If endproc is specified, it is called when the sequence has completed. Note that running sequences require the event loop.

The endproc command, if specified, is called with the SequenceRunner object, the completion status and a reason for the completion. SequenceRunner objects are described in SEQUENCE RUNNER OBJECTS below. The status can be either OK or ABORTED with meanings that should be clear. The reason is a user readable reason for the completion. This is an empty string for

sequence::transition db transition ?endscript?

Runs a transition to the state specified by transition. For the transition to succeed, all steps in all sequences must complete successfully. If endscript is specified, it is invoked at the end of the attempted transition. Note that as with sequence::runSequence, the event loop is needed to execute the transition.

If specified, the end script is invoked with the database command, the Transition Manager (see TRANSITION MANAGER OBJECTS below), and completion status. The completion status is one of OK successful completion, ABORTED the sequence executaion was aborted (the system is not in a well defined state). SHUTDOWN, sequence execution failed and the system forced a transition to the SHUTDOWN initial state.

sequence::getCurrentTransition

Returns the base command of the transition manager that is performing the current transition. If no transition is in progress, an empty string is returned. See TRANSITION MANAGER OBJECTS for information about transition managers.

sequence::relayOutput text

Relays the text to all clients of the output relay server. See OUTPUT RELAY SERVER below for more information.

TRANSITION MANAGER OBJECTS

When the sequence package performs a transition, it instantiates a transition manager object. This object, runs all of the sequences triggered by the transition and invokes any script associated with the end of the transition. The Tcl/Tk event loop is required to both to perform sequences and the transition as a whole.

The transition manager object instances are are instances of a snit::type named sequence::TransitionManager. This section describes the options and methods of that object.

OPTIONS

-database

This readonly (must be set at construction time) option must be set with the database connection command. The connection command must be valid for the duration of the transition.

-type

This readonly option must be set with the desired final state of the system.

-endscript

This option can be modified any time before the transition ends. If, when the transition ends, it is non empty, it is assumed to contain a script that is evaluated at the global level with the database command, the transition manager instance command, and the transition completion status. The completion status is one of OK successful completion, ABORTED the sequence executaion was aborted (the system is not in a well defined state). SHUTDOWN, sequence execution failed and the system forced a transition to the SHUTDOWN initial state.

METHODS

start

Starts the transition managed by the instance. If the transition is already in progress, this method reports an error.

If there are no sequences triggered by this transition, the transition completes immediately. Otherwise, the sequences are executed from the event loop.

abort

Aborts the transition. The state remains unchanged, however it's not, in general, possible to reverse sequence steps already performed. The current sequence is aborted. The transition end is signalled with the status ABORTED.

isActive

Returns a boolean that is true valued if the transition is active and false valued if not.

currentSequence

Returns the name of the currently active sequence in the transition.

SEQUENCE RUNNER OBJECTS

Sequence runner objects are used to manage the execution of the steps in a sequence. They are instances of the snit::type sequence::SequenceRunner. Sequence execution requires the event loop.

OPTIONS

-database

The SQLite3 database connection command

-name

Name of the sequence.

-steps

List of step definition dicts. These are the output of sequence::listSteps

-endcommand

If not an empty string, this is a script that will be invoked when the sequence finishes running. The script will receive three actual parameters. The command that represents the sequence::SequenceRunner instance, the completion status which will be one of NORMAL or ABORT and a text string that, if the completion reason was ABORT describes why the sequence was aborted.

METHODS

OUTPUT MONITOR OBJECTS

The following public methods are exported by sequence::SequenceRunner objects. They are intended for use by the sequence::TransitionManager as it executes sequences associated with its transition, however they can be used for test purposes as well.

start

Starts sequence execution. Sequence execution relies on the event loop to dispatch its execution of each step.

abort ?reason?

Aborts sequence execution. The sequence will complete immediately. Any -endcommand will be executed with the reason ABORT and the reason text string given by the optional reason parameter which, if not provided defaults to Programmatically aborted

OUTPUT RELAY SERVER

WHen the sequence package is loaded it starts a server on an advertised service name. The name of the service is the value of the environment variable SERVICE_NAME with -outputMonitor appended. Note that when the manager is run, the environment variable SERVICE_NAME is set to the name of the service the manager advertises for REST interactions.

For test purposes, if the SERVICE_NAME environment variable is not defined the service name dummy-outputMonitor is used instead.

The server started in this manner accepts connections from clients and sends them the text that's passed to the command sequence::relayOutput. All clients receive this text.

By default, output from programs that are run in sequences are sent to the ::sequence::relayOutput command. In practice, this means that this service provides combined output from all programs both persistent and transitory.