NAME

EPICS::IOC - Manage an EPICS IOC

SYNOPSIS

    use EPICS::IOC;

    my $ioc = EPICS::IOC->new;
    $ioc->debug(1);       # Show IOC stdio streams

    $ioc->start('bin/@ARCH@/ioc', 'iocBoot/ioc/st.cmd');
    $ioc->cmd;            # Wait for the iocsh prompt

    my @records = $ioc->dbl;
    my @values = map { $ioc->dbgf($_); } @records;

    $ioc->kill;

DESCRIPTION

This module provides an object-oriented API for starting, interacting with and stopping one or more EPICS IOCs under program control, and is generally intended for writing test programs.

The IOC should not be configured to emit unsolicited messages on stdout as this could interfere with the ability of the software to detect an end-of-command from the IOC shell, which is achieved by setting the prompt to a known string (normally __END__). Unsolicited messages on stderr will not cause problems, but can't be seen on Windows systems.

CONSTRUCTOR

new ()

Calling new creates an EPICS::IOC object that can be used to start and interact with a single IOC. After this IOC has been shut down (by calling its kill method) the EPICS::IOC object may be reused for another IOC.

METHODS

debug ( [FLAG] )

Each EPICS::IOC object has its own debug flag which when non-zero causes all IOC console traffic sent or read by other methods to be printed to stdout along with the IOC's pid and a direction indicator. The debug method optionally sets and returns the value of this flag.

The optional FLAG is treated as a true/false value. If provided this sets the debug flag value.

The method's return value is the current (new if given) value of the flag.

start ( EXECUTABLE [, ARGUMENTS ...] )

Launch an IOC binary given by EXECUTABLE with ARGUMENTS. The method dies if it can't run the program as given, or if the IOC is already running.

In most cases the cmd method should be called next with no command string, which waits for the IOC's boot process to finish and the first iocsh prompt to be displayed.

The start method sets two environment variables that control how the IOC shell behaves: IOCSH_HISTEDIT_DISABLE is set to prevent it calling the GNU Readline library, and IOCSH_PS1 is set to a known string which is used as a terminator for the previous command.

pid ()

Returns the process-ID of the IOC process, or undef if the IOC process has not yet been started.

started ()

Returns a true value if the IOC has been started and not yet killed. This state will not change if the IOC dies by itself, it indicates that the start method has been called without the kill method.

_send ( COMMAND )

The _send method is a primitive for internal use that sends a COMMAND string to the IOC shell, and prints it to stdout if the debug flag is set.

_getline ()

The _getline method is also designed for internal use, it fetches a single line output by the IOC, and prints it to stdout if the debug flag is set.

Any CR/LF is stripped from the line before returning it. If the stream gets closed because the IOC shuts down an EOF debug message may be shown and an undef value will be returned.

_getlines ( [TERM] )

Another internal method _getlines fetches multiple lines from the IOC. It takes an optional TERM string or regexp parameter which is matched against each input line in turn to determine when the IOC's output has been completed. Termination also occurs on an EOF from the output stream.

The return value is a list of all the lines received (with the final CR/LF stripped) including the line that matched the terminator.

_geterrors ( )

Returns a list of lines output by the IOC to stderr since last called. Only complete lines are included, and trailing newlines have been removed.

NOTE: This doesn't work on Windows because it uses select which Perl doesn't support on that OS, but it doesn't seem to cause any problems for short-lived IOCs at least, it just never returns any text from the IOC's stderr output.

cmd ( [COMMAND [, ARGUMENTS ...]] )

If the cmd method is given an optional COMMAND string along with any number of ARGUMENTS it constructs a command-line, quoting each argument as necessary. This is sent to the IOC and a line read back and discarded if it matches the command-line.

With no COMMAND string the method starts here; it then collects lines from the IOC until one matches the terminator. A list of all the lines received prior to the terminator line is returned.

kill ()

The kill method attempts to stop an IOC that is still running in several ways. First it sends an exit command to the IOC shell. Next it closes the IOC's stdin stream which will trigger an end-of-file on that stream, and it fetches any remaining lines from the IOC's stdout stream before closing both that and the stderr stream. Finally (unless running on MS-Windows) it sends a SIGTERM signal to the child process and waits for it to clean up.

DESTROY ()

EPICS::IOC objects have a destructor which calls the kill method, but it is not recommended that this be relied on to terminate an IOC process. Better to use an END {} block and/or trap the necessary signals to explicitly kill the IOC.

CONVENIENCE METHODS

The following methods provide an easy way to perform various common IOC operations.

dbLoadRecords ( FILE [, MACROS] )

Instructs the IOC to load a database (.db) from FILE. If provided, the MACROS parameter is a single string containing one or more comma-separated assignment statements like a=1 for macros that are used in the database file.

This method can also be used to load a database definition (.dbd) file.

iocInit ()

Start the IOC executing.

dbl ( [RECORDTYPE])

This method uses the dbl command to fetch a list of all of the record names the IOC has loaded. If a RECORDTYPE name is given, the list will only comprise records of that type.

dbgf ( PV )

The dbgf method returns the value of the process variable PV, or undef if the PV doesn't exist. This only works when the PV holds a scalar or an array with one element.

dbpf ( PV, VALUE )

This method sets PV to VALUE, and returns the new value, or undef if the PV doesn't exist. If the put fails the return value is the previous value of the PV. As with the dbgf method this only works for scalar or single-element arrays, but PV may be an array field which will be set to one element.

COPYRIGHT AND LICENSE

Portions Copyright (C) 2011 UChicago Argonne LLC, as Operator of Argonne National Laboratory.

This software is distributed under the terms of the EPICS Open License.