Interoperating with Alfred
Requirements for Typical and "Persistent" Applications


Consider the following command specification taken from an alfred script:

	##AlfredToDo 2.0
	Task "frame one" -cmds {
		Cmd {render 001.rib}
	}
When the dispatcher reaches this point in the job it will fork(2) a child process and use the library routine execvp(2) to launch the program named "render" (assuming there is one in the current path). The launch process is described in more detail in the dispatching discussion.

Alfred-Compliant Application Behavior

Alfred expects that the applications it launches will follow a few simple rules: These are standard attributes of many existing applications. Alfred collects both stdout and stderr from the launched applications and logs the output into an archive that can be retrieved by users on a per-task basis using the UI.

Progress Indication and Alternate Exit Status

Applications can send a few special messages to alfred to trigger certain special behavior. Sometimes it's useful for long-running commands, such as renderings, to send percent-done messages to alfred so that it can periodically update it's Task diagram to indicate command progress. Alfred scans the stderr and stdout from the application looking for (newline-delimited) lines of form:
	ALF_PROGRESS nn%
where "nn" is an integer 0-100 which indicates the current percent-completion of the command.

Similarly, lines of the form "ALF_EXIT_STATUS nnn" are used to override the subsequent real exit status of the command. This is particularly useful for applications which are launched indirectly via a call to rsh(1), since rsh exits with its own status, not the status of the remotely launched command.  


Persistent Applications

In some circumstances it is useful for alfred to launch an application once at the beginning of a job and subsequently send it command messages throughout the lifetime of the job. Typically this is done to avoid long launch times when multiple commands will be processing the same input file or database, etc. These are called "persistent applications," an important example of which is the stand-alone version of mtor, which is used to process Maya® model files that have been enhanced using the MTOR plug-in. For example, the stand-alone mtor is launched with the name of a scene file, then messages are sent to its stdin which cause it to generate RIB, or even run-time additions to the alfred job, on demand.

In terms of the alfred scripting language, a persistent application is simply one which:

That is, the persistence is really a function of the application. It is launched and sent the (optional) message just like any other command. If it processes the message and exits, then alfred considers the command complete and goes on to the next one. If it processes the message but does not exit, then alfred looks ahead in the script to see if another instance of the same invocation occurs, if so the next message is sent without relaunching the app when it gets to that point in the script. Here is an example from our ATOR product...
	[...]
	Task "Frame.0000" -cmds {
		Cmd {ator -alfred /tmp/xmp.wire.a005Ji} \
			-msg {genWorklist 0 nohost flush} \
			-tags {intensive} -expand 1
	}

	Task "Frame.0001" -cmds {
		Cmd {ator -alfred /tmp/xmp.wire.a005Ji} \
			-msg {genWorklist 1 nohost flush} \
			-tags {intensive} -expand 1
	}
	[...]
In this case the application "ator" is launched to process the "genWorklist 0 ..." command. The launch itself requires the potentially lengthy start-up processing of a wire file. If ator hasn't exited when the Frame.0001 task is started, then the "genWorklist 1 ..." message is sent to the still-running app, without requiring a reload of the wire file. Note: if ator did exit between commands, then the normal command launching would occur again for Frame.0001.

Note: by default alfred will attempt to launch as many Ready leaf nodes as possible in parallel. This means that script writers need to take care to avoid having parallel invocations of an application that was intended to be persistent. One simple way to avoid multiple invocations is to define a limit in the alfred schedule for the app name. The default alfred schedule limits the number of simultaneous local invocations of ator and mtor to one. In the example above, the tag "intensive" is also used to indicate that the given message will trigger a heavy-weight operation, such as traversing a model and generating a RIB file. In this case the script assumes that there is a limit of one intensive Cmd allowed at a time (this is the setting in the default schedule). Note that both the launched app name and any explicitly listed tags are checked against the current limits; matching service types can also be limited.

After all references to a persistent application have been processed, alfred attempts to close the persistent application using an increasingly severe series of actions. First it will close the application's stdin pipe. If the application doesn't exit, alfred then sends it a SIGTERM signal; and finally if that hasn't worked, a SIGKILL is sent.

For an application to work as a persistent application:

These last two points are crucial since alfred relies on these two behaviors to determine when a message has been successfully processed (in the current implementation each outgoing message has a feedback "echo" command appended to it, when alfred gets this marker back it knows the message has been processed).
 

Pixar Animation Studios
(510) 752-3000 (voice)   (510) 752-3151 (fax)
Copyright © 1996- Pixar. All rights reserved.
RenderMan® is a registered trademark of Pixar.