source: trunk/gui/scripts/tool.tcl @ 413

Last change on this file since 413 was 413, checked in by mmc, 18 years ago
  • Added <description> capability to output objects, including axes.
  • Fixed the ResultSet? so that it is more compact and supports the simulation number as a parameter. This is useful when there are datasets with wildly varying parameters.
File size: 7.0 KB
Line 
1# ----------------------------------------------------------------------
2#  COMPONENT: tool - represents an entire tool
3#
4#  This object represents an entire tool defined by Rappture.
5#  Each tool resides in an installation directory with other tool
6#  resources (libraries, examples, etc.).  Each tool is defined by
7#  its inputs and outputs, which are tied to various widgets in the
8#  GUI.  Each tool tracks the inputs, knows when they're changed,
9#  and knows how to run itself to produce new results.
10# ======================================================================
11#  AUTHOR:  Michael McLennan, Purdue University
12#  Copyright (c) 2004-2005  Purdue Research Foundation
13#
14#  See the file "license.terms" for information on usage and
15#  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
16# ======================================================================
17package require BLT
18
19itcl::class Rappture::Tool {
20    inherit Rappture::ControlOwner
21
22    constructor {xmlobj installdir args} {
23        Rappture::ControlOwner::constructor ""
24    } { # defined below }
25
26    public method installdir {} { return $_installdir }
27
28    public method run {args}
29    public method abort {}
30
31    protected method _output {data}
32
33    private variable _installdir ""  ;# installation directory for this tool
34    private variable _outputcb ""    ;# callback for tool output
35    private common job               ;# array var used for blt::bgexec jobs
36    private common jobnum 0          ;# counter for unique job number
37
38    # resources file tells us the application name
39    public common _appname ""
40    public proc setAppName {name} { set _appname $name }
41}
42
43# must use this name -- plugs into Rappture::resources::load
44proc tool_init_resources {} {
45    Rappture::resources::register \
46        application_name Rappture::Tool::setAppName
47}
48                                                                               
49# ----------------------------------------------------------------------
50# CONSTRUCTOR
51# ----------------------------------------------------------------------
52itcl::body Rappture::Tool::constructor {xmlobj installdir args} {
53    if {![Rappture::library isvalid $xmlobj]} {
54        error "bad value \"$xmlobj\": should be Rappture::Library"
55    }
56    set _xmlobj $xmlobj
57
58    if {![file exists $installdir]} {
59        error "directory \"$installdir\" doesn't exist"
60    }
61    set _installdir $installdir
62
63    eval configure $args
64}
65
66# ----------------------------------------------------------------------
67# USAGE: run ?<path1> <value1> <path2> <value2> ...? ?-output <callbk>?
68#
69# This method causes the tool to run.  All widgets are synchronized
70# to the current XML representation, and a "driver.xml" file is
71# created as the input for the run.  That file is fed to the tool
72# according to the <tool><command> string, and the job is executed.
73#
74# Any "<path> <value>" arguments are used to override the current
75# settings from the GUI.  This is useful, for example, when filling
76# in missing simulation results from the analyzer.
77#
78# If the -output argument is included, then the next arg is a
79# callback command for output messages.  Any output that comes in
80# while the tool is running is sent back to the caller, so the user
81# can see progress running the tool.
82#
83# Returns a list of the form {status result}, where status is an
84# integer status code (0=success) and result is the output from the
85# simulator.  Successful output is something like {0 run1293921.xml},
86# where 0=success and run1293921.xml is the name of the file containing
87# results.
88# ----------------------------------------------------------------------
89itcl::body Rappture::Tool::run {args} {
90    global errorInfo
91
92    # make sure that we save the proper application name
93    if {"" != $_appname} {
94        $_xmlobj put tool.name $_appname
95    }
96
97    # sync all widgets to the XML tree
98    sync
99
100    # if there are any args, use them to override parameters
101    set _outputcb ""
102    foreach {path val} $args {
103        if {$path == "-output"} {
104            set _outputcb $val
105        } else {
106            $_xmlobj put $path.current $val
107        }
108    }
109
110    foreach item {control output error} { set job($item) "" }
111
112    # write out the driver.xml file for the tool
113    set file "driver[pid].xml"
114    set status [catch {
115        set fid [open $file w]
116        puts $fid "<?xml version=\"1.0\"?>"
117        puts $fid [$_xmlobj xml]
118        close $fid
119    } result]
120
121    # set limits for cpu time and file size
122    set limit [$_xmlobj get tool.limits.cputime]
123    if {"" == $limit || [catch {Rappture::rlimit set cputime $limit}]} {
124        Rappture::rlimit set cputime 900  ;# 15 mins by default
125    }
126
127    set limit [$_xmlobj get tool.limits.filesize]
128    if {"" == $limit || [catch {Rappture::rlimit set filesize $limit}]} {
129        Rappture::rlimit set filesize 1000000  ;# 1MB by default
130    }
131
132    # execute the tool using the path from the tool description
133    if {$status == 0} {
134        set cmd [$_xmlobj get tool.command]
135        regsub -all @tool $cmd $_installdir cmd
136        regsub -all @driver $cmd $file cmd
137
138        # starting job...
139        Rappture::rusage mark
140
141        set status [catch {eval blt::bgexec \
142            ::Rappture::Tool::job(control) \
143            -keepnewline yes \
144            -killsignal SIGTERM \
145            -onoutput [list [itcl::code $this _output]] \
146            -output ::Rappture::Tool::job(output) \
147            -error ::Rappture::Tool::job(error) $cmd} result]
148
149        # ...job is finished
150        array set times [Rappture::rusage measure]
151        puts stderr "MiddlewareTime: job=[incr jobnum] event=simulation start=$times(start) walltime=$times(walltime) cputime=$times(cputime) status=$status"
152
153    } else {
154        set job(error) "$result\n$errorInfo"
155    }
156    if {$status == 0} {
157        file delete -force -- $file
158    }
159
160    # see if the job was aborted
161    if {[regexp {^KILLED} $job(control)]} {
162        return [list 0 "ABORT"]
163    }
164
165    #
166    # If successful, return the output, which should include
167    # a reference to the run.xml file containing results.
168    #
169    if {$status == 0} {
170        set file [string trim $job(output)]
171        return [list $status $file]
172    } elseif {"" != $job(output) || "" != $job(error)} {
173        return [list $status [string trim "$job(output)\n$job(error)"]]
174    }
175    return [list $status $result]
176}
177
178# ----------------------------------------------------------------------
179# USAGE: abort
180#
181# Clients use this during a "run" to abort the current job.
182# Kills the job and forces the "run" method to return.
183# ----------------------------------------------------------------------
184itcl::body Rappture::Tool::abort {} {
185    set job(control) "abort"
186}
187
188# ----------------------------------------------------------------------
189# USAGE: _output <data>
190#
191# Used internally to send each bit of output <data> coming from the
192# tool onto the caller, so the user can see progress.
193# ----------------------------------------------------------------------
194itcl::body Rappture::Tool::_output {data} {
195    if {[string length $_outputcb] > 0} {
196        uplevel #0 [list $_outputcb $data]
197    }
198}
Note: See TracBrowser for help on using the repository browser.