Contributors
Ben Allan, Rob Armstrong, Colin Potter
Change history
CCAFFEINE (Common Component Architecture Fast Framework Example In Need
of Everything) is the first Sandia testbed implementation of a component
software framework supporting the standards proposals published by the
Common Component Architecture Forum. Our two purposes in writing are to
solicit technical suggestions and criticism (dope slaps?) for the proposed
version 1 wire protocol currently in design for CCAFFEINE and to document
the allegedly scalable command and control structure and the version 0 wire
protocol presently used in CCAFFEINE.
First, we very briefly review the current command and control strategy
used in CCAFFEINE. It would be overstating the case to claim that the
accumulated code which handles these tasks was designed beyond the most
basic structural levels. Second section, we list the objectives we believe
need to be considered when replacing the remote control layer. Finally, we
present an initial design of the replacement for review by the larger
community.
We document the current wire protocol and message transport scheme used
in CCAFFEINE for the runtime management of HPC software components to
motivate a new design and to capture many relevant use-cases. We are not
writing a reference manual to support future users of an existing product.
We hope the documentation of several failings in the initial implementation
may save time for later implementers and designers.
(Put some pictures here that explain our sockets, muxers, and CmdLineBuildViews and the process of starting up CCAFFEINE).
As seen in UI Servers and SPMD Clients the
CCAFFEINE GUI drives the framework by sending it strings through a socket
connection. Thus each GUI feature is implemented as some combination of
framework line-oriented commands and (minimal) GUI-cached data. We will
document the command-line syntax and semantics in Appendix A.
The current CCAFFEINE GUI has buttons, features, and bindings (actions)
as summarized in the following list. We name these items in a dot notation
to indicate a conceptual hierarchy that organizes the information and
functions delivered by the GUI. This does not correspond to a specific
hierarchy of widgets in the implementation or to a specific display
layout.
GUI.title | Publicity string naming the system and the demo being shown. |
file.new | forget the existing components and start a new screen |
file.quit | exit the GUI and cause linux kernel failure if using mpich/c++ frame. Just quit if pure java. |
help.about_this_demo | display about file from disk (html) |
open_and_execute .bld file. | replay history file |
save .bld file as | save history file |
pallette.fill from framework list | load list of component classes into GUI |
pallette.pick | nominate class for next instantiation in arena |
remove | delete picked arena instance |
remove all | delete all arena instances and clear history. |
run | fire all go ports in arena. probably a really bad idea. |
arena.component.pick | highlight in blue/nominate component instance for next arena action |
arena.component.drop | normal finish of pallet.pick process. create an instance and draw icon at GUI drop location. |
arena.component.move | reposition instance icon in the arena GUI |
arena.component.port.pick_source | highlight uses port to connect next. |
arena.component.port.pick_target_and_connect | select providing port and attempt connection. |
arena.component.port.pick_go | select and execute go port. |
arena.component.port.pick_config | select port and initiate configuration parameters dialog |
paramDialog.ok | dismiss parameter port dialog and feed configs back to framework. |
paramDialog.cancel | dismiss parameter port dialog |
arena.component.port.hover | display port type |
paramDialog.* | See Appendix B, Generic Configuration Port. |
We seek a wire protocol (event strings over sockets) for managing a heavy, remote, "mostly single threaded" parallel framework from java/tk/python/other shell languages. The protocol should be such that a GUI can optimize some aspects of its rendering while becoming consistent with the remote framework state if the user waits an appropriate amount of time. In particular, it should not be such that the GUI offers services before they are really there or that it continues to offer services after they are definitely *not* there. Given lags in network transport and long pauses while computations progress, it is not efficient to fully synchronize a largely passive (frame the parallel job then get out of the way) remote GUI rendering with its phalanx of controlled processes. This scope may be rather distinct from the loosely coupled system represented by the Indiana framework.
The framework and protocols we describe here are aimed at supporting framework developers, component developers, and component testers using the software on a workstation emulating a multiprocessor or a small set of processors in a larger SPMD machine. Most tightly coupled, massively parallel platforms we are aware of provide such an interactive environment for development purposes, while production runs are large, batch-queued, and non-interactive. Interaction with production runs is often through examination of periodically dumped checkpoint files or editing of a periodically reread parameter file.
The minimum result we require from CCAFFEINE is that the actions of an interactive session can be recorded as a script which can be reread as the control file for a non-interactive production run where only a lightweight C++ framework backend is present. The other result we expect to obtain is that we can generate a C++ main() which is equivalent to the script, but requires no string interpreters and only an extremely lightweight framework backend without the CCAFFEINE control sockets outlined in UI Servers and SPMD Clients.
GUI.title | string from GUI author. |
framework title | goes in the container titles issued by the framework; not a separate facility. |
file.new | GUI sends a request for a new named containernewContainer <name>
newContainer <name> GUI renders named pallet and arena into its collection of pages on receipt of the arena/pallet end <name>. The pallet may be empty. (The GUI has a separate facility to support the framework api that adds classes to a (possibly empty) pallet. The arena may be empty. It may not if the framework chooses to preinstantiate some components always! Notes: The GUI cannot be certain the framework is done with a new container and should be capable of accurate partial rendering of the container. Similarly, the GUI cannot be certain of receiving either pallet end <name> or arena end <name>. The intent of the "end" events is to give the GUI a backstop event for those times where the GUI wants to skip the rendering phase of adding to its list of managed classes/instances until "all" have been received or a specified timeout since last newClass event has occured. This allows optimization (minimization) of GUI redraws; e.g. wait until all the classes are in (or a timeout) and then resize pallet to hold the widest label. |
GUI.about | anything the GUI author implements |
framework.about | GUI sends a request for about info containerAbout <name>
containerAbout <name> <html> ... </html>
Notes: Between <html> and </html> there may be line breaks. </html> may be assumed to occur on a line by itself for sloppy prototype implementations if needed. |
file.attach | GUI attaches to a running framework and sends introspection
request:
fwkDump GUI returns to passivity. framework sends back event sequence which will be fwkDump begin <fwkName> [0 or more newContainer sequences as described for file.new] [0 or more newComponent sequences as described for file new] fwkDump end <fwkName> framework flushes from its queue any events that an overeager user tried to schedule while the GUI was catching up with output from the framework. |
container.close | send a single request to the framework to close and destroy the
named container.
containerClose <name> GUI returns to passivity. framework sends back (if lucky) containerClose <name> GUI may de-render the container at any time after containerClose is sent. Notes: It may be desirable for the GUI to queue to itself the teardown event to be done in X seconds. The containerClose event from the framework should cause immediate de-rendering of the container on the GUI side. A teardown event on a non-existent container must not be an error. Tearing down a container must cause cancel and teardown of any open dialogs associated with it. containerClose <name> may also generate messages as in "remove picked arena instance" below. |
file.detach | GUI unregisters as a framework listener and tears down all the renderings of containers. |
file.quit | GUI sends exit command to the framework. GUI does file.detach above. GUI exits. framework will shutdown on its own at next convenient point which may be after a long computation finishes. |
file.quit_now_damnit | GUI sends stop command to the framework. GUI does file.detach above. GUI displays instructions to user about how to kill the framework job if it doesn't die nicely on its own. GUI exits. framework will shutdown immediately (or at next checkpoint in computation). If this is not soon enough, user can follow instructions about killing processes. |
cca.about_this_demo: | see framework.about above. |
open_and_execute .bld file save .bld file: save .bld file as: | These need further thought, as we have the following small conundrum- .bld is really a history file. presently it is a history of the GUI issued commands. But if the GUI comes and goes, then the history of a container in the framework must be kept in the framework not in the GUI. So then we need a command for the GUI to query the container for the history string. |
pallette.fill from framework list | subsumed by container above, though implemented separately. |
pallette.pick | nominate class for next arena drop or other query GUI-only. no implication on framework. |
remove picked arena instance | GUI send remove request.remove <container-name> <comp-name>
disconnect <container-name> <comp> <port> <comp> <port> commands which cause the GUI to de-render the connection or component. Notes: if a component is de-rendered, any open dialogs for it should also be de-rendered and actions equivalent to cancel taken. The delete and disconnect commands must deal gracefully (silently) with names the GUI no longer recognizes/already de-rendered. |
remove all arena instances and clear history | implement as close.container <name>;file.new <name>. |
run | (fire all go ports in arena. probably a really bad idea now): just delete this feature. |
arena.component.pick | (highlight in blue/nominate for next arena action) GUI-only. no implication on framework. |
arena.component.drop | Normal finish of pallet.pick-arena.create. GUI send create request to framework. pulldown containerName className compName
newComponent <class-name> <instance-name> <name> |
arena.component.describe | GUI send request for port and other component properties.display component <containerName> <compName>
|
arena.component.move | reposition in the GUI. GUI-only. no implication on framework. |
arena.component.port.pick_source | highlight uses port to connect. GUI-only. no implication on framework. |
arena.component.port.pick_target_and_connect | select providing port. GUI send request for connection.connect <containerName> <component> <port> <component> <port>
connect <containerName> <component> <port> <component> <port> |
arena.component.port.pick_go | highlight and execute go port. GUI send request for execution. go <containerName> <component> <port>
|
arena.component.port.pick_config | highlight and execute config port. GUI send request for config info configure <containerName> <component> <port>
|
paramDialog.ok | Dismiss dialog and feed configs back to framework. GUI send parameter set requests to framework. GUI return to passive state. |
paramDialog.cancel | dismiss dialog. GUI-only. no implication on framework. teardown dialog window. |
Lots more to be added. See TODO-list and then get inspired to extend here. E.g. RepositoryService, SemaphoreService,AboutService, HelpService, GeneralDialogService, control of Nestable containers, Port property hints (rendering), component property hints (rendering), framework properties (rendering). GlobalResourceStringService ala Argonne integrated with parameter dialog wire protocol.
Aliases | Arguments and Description |
help, ? | arguments: [string token]
Prints the help of one or all commands. This table is the annotated version of the "help" output. |
exit, bye, quit, x | arguments: [string token]
Exits the parser, returning control to the parser caller. If string is given, it is converted to an integer return value. |
connect | arguments: <using instance> <used Port name> <providing
instance> <provided Port name>
Connect two components in the arena. NOTE! According to the draft specification, either or both components may do any of the following when receiving the ConnectionEvent after the connection is made: immediately use the connected port and delete it or other ports, add new ports, or nearly anything else. Expect surprises when using new components. |
configure, parameters | arguments: <instance> <parameterPortName>
<parameterName> [newValue]
Query (or set new value) of named parameter (field) in the named port of the named component instance. The special field (parameterName) ALL is recognized (when newValue is omitted) and causes the framework to send back a full description of the port as outlined in Appendix B. |
display arena | List component instances known in the arena. (not expected to remain in future releases, see arena below) |
display pallet | List component classes available in the pallet. (not expected to remain in future releases, see pallet below) |
display component | arguments: <instanceName>
Show class name and ports defined for the named instance in the arena. (not expected to remain in future releases, see show below) |
display chain | arguments: <instanceName>
List all connections in the arena. The instance name given is irrelevant. Connections are grouped by their 'using' component. Connections with a releasePort() call outstanding are listed as ACTIVE. (not expected to remain in future releases, see links below) |
go, run | arguments: [instanceName portName]
Execute the go() function of the named port on the named instance. Presently, if the names are omitted, all Go ports in the arena are fired in an arbitrary sequence. |
create, instantiate, pulldown | arguments: <className> [instanceName]
Add an instance of named class to the arena. The instance name may be supplied. If not, a unique instance name will be generated from the class name. |
pallet, classes | List component classes available in the pallet. |
arena, instances | List component instances known in the arena. |
remove | arguments: <instanceName>
Delete the named instance from arena. Probably a very buggy thing to do in alpha releases of the framework. |
nuke | Destroy all of the components in the arena. Probably a very buggy thing to do in alpha releases of the framework. |
path | arguments: [keyword] [directory/path]
Manipulate the path searched for CCA components. With no arguments, displays the current path. Keyword init initializes the path from env(CCA_COMPONENT_PATH). Keyword append/prepend followed by a directory name extends the path to include that directory. Keyword set followed by a shell-style path replaces the current search path with a new one. |
repository | arguments: <keyword> [repositoryClassName]
Keyword list returns the known components in the repository that are not yet loaded. Keyword get followed by a classname returned from repository list dynamically loads the class into the framework. Keyword info followed by a className gives the metadata associated with the className. (Info is not yet implemented). |
links (not implemented) | List all connections in the arena, grouped by using component. Connections with a releasePort() call outstanding are listed as ACTIVE. (Replacement for "display chain".) |
show (not implemented) | arguments: <instanceName>
Show class name and ports defined for the named instance in the arena. |
We provide a basic, UI-independent parameter input request protocol that lets the component developer assume primitive input sanity. One GUI rendering of the input request protocol, the paramDialog, is described in the second table below. The first table below gives the protocol itself, the line-oriented commands sent from the framework to the GUI. The UI optional response to these commands is to send back configure commands for one or more of the fields of the parameter dialog according to the description in Appendix A.
The protocol could be easily replaced with a single dialog display command using an XML description of the parameter input request. The series of commands is sent in an order that will allow any reasonable object-oriented UI implementation to build temporary data structures needed to negotiate with the user.
The first shortcoming of the protocol is that it may need to have inserted a lead argument to all commands which lets the UI discriminate among multiple containers. I.e. everywhere in the protocol that arguments instance port appear we may need to extend to containerInstance instance port . The second shortcoming of the protocol is that it requires the UI implementation to associate each paramField received with the most recently received paramTab in the given dialog. It would be preferable to include a tabName in the arguments associated with individual fields.
command | arguments and explanation |
paramDialog | arguments: <instanceName> <portName>
<dialogTitle...>
Inform the UI that the framework wants a dialog to get the values of one or more scalar variables (parameter fields) from the user. Each port of type ParameterPort on a CCA instance is associated with a separate dialog. There may be several such ports, uniquely named, per instance. The dialogTitle is a string terminated by the newline. It cannot be empty. |
paramTab | arguments: <instanceName> <portName> <groupTitle...>
When the dialog has lots of fields, they need to be broken up into groups of more closely related values. This is typically graphically rendered as a tabbed dialog or other series of panels. The groupTitle is a string, as the dialog title. It cannot be empty. |
paramField | arguments: <instanceName> <portName> <fieldType>
<fieldName>
Add a new field to the most recently defined group. FieldType is one of: DOUBLE, INT, FLOAT, LONG, BOOL, and STRING. |
paramPrompt | arguments: <instanceName> <portName> <fieldName>
<promptString...>
With each field is a (hopefully concise) string to clue the user about what is reqested. The promptString cannot be empty. |
paramCurrent | arguments: <instanceName> <portName> <fieldName>
<value...>
Each field has a current value. Only in the case of un-enumerated STRING fields is it possible that the value is empty, in which case the degenerate form of the command will occur: arguments: <instanceName> <portName> <fieldName> |
paramDefault | arguments: <instanceName> <portName> <fieldName>
<value...>
Each field has a default value. The description is as for paramCurrent. |
paramNumberRange | arguments: <instanceName> <portName> <fieldName>
<low> <high>
The numerical field types have lower and upper bounds. The UI must use these to filter out bogus input. |
paramStringChoice | arguments: <instanceName> <portName> <fieldName>
<string...>
For STRING parameters which are limited to a selection (such as from a pulldown list) each choice of value is sent in a separate command of this form. |
paramHelp |
arguments: <instanceName> <portName> <fieldName>
<string...>
Each field may have a longer explanation associated with it. That explanation is in the form of a string. It should not be rendered by default, but only when the user asks for it. |
paramEndDialog | arguments: <instanceName> <portName>
This optional command tells the UI that the framework is done sending information about the dialog specified by instance and port. The UI may choose to render the dialog partially as commands are received from the framework. When a paramEndDialog is received, the UI must render, if it has not already. The UI might, if a reasonable timeout has expired since the last command wrt the dialog was received, assume the dialog request is complete and render anyway. |