Changeset 6473
- Timestamp:
- Aug 7, 2016 6:08:40 PM (8 years ago)
- Location:
- trunk
- Files:
-
- 8 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk
- Property svn:mergeinfo changed
-
trunk/gui/apps/launcher.tcl
r6296 r6473 1 1 #!/bin/sh 2 # -*- mode: Tcl -*-2 # -*- mode: tcl; indent-tabs-mode: nil -*- 3 3 # ---------------------------------------------------------------------- 4 4 # RAPPTURE LAUNCHER … … 44 44 45 45 set rapptureInfo(cwd) [pwd] 46 set rapptureInfo(appName) "" 46 47 47 48 if {[info exists env(TOOL_PARAMETERS)]} { … … 80 81 lappend params(load) $value 81 82 set params(opt) "-load" 83 } 84 "(simset)" - "" { 85 lappend params(simset) $value 86 set params(opt) "-simset" 82 87 } 83 88 "(execute)" { … … 176 181 } 177 182 } 183 -simset { 184 lappend alist $opt [lindex $argv 0] 185 set argv [lrange $argv 1 end] 186 } 187 -appname { 188 global rapptureInfo 189 set rapptureInfo(appName) [lindex $argv 0] 190 set argv [lrange $argv 1 end] 191 } 178 192 default { 179 193 puts stderr "usage:" … … 202 216 set reqpkgs Tk 203 217 } 218 -simset { 219 # add tool parameters to the end of any files given on cmd line 220 set loadlist [concat $loadlist $params(simset)] 221 set alist [concat $alist -simset $loadlist] 222 223 package require RapptureGUI 224 set guidir $RapptureGUI::library 225 set mainscript [file join $guidir scripts main.tcl] 226 set reqpkgs Tk 227 } 204 228 -execute { 205 229 if {[llength $params(execute)] != 1} { … … 260 284 # Note: We're sourcing the driver file "main.tcl" rather than exec-ing 261 285 # wish because we want to see stderr and stdout messages when they 262 # 263 # 264 # 265 # 286 # are written, rather than when the program completes. It also 287 # eliminates one process waiting for the other to complete. If 288 # "exec" is needed, then the following could be replaced with 289 # blt::bgexec. It doesn't try to redirect stderr into a file. 266 290 set argv $alist 267 291 foreach name $reqpkgs { -
trunk/gui/scripts/analyzer.tcl
r6030 r6473 60 60 public method reset {{when -eventually}} 61 61 public method load {xmlobj} 62 public method reload { fileName } 62 63 public method clear {{xmlobj "all"}} 63 64 public method download {option args} 65 public method buildMenu { w url appName } 64 66 65 67 protected method _plot {args} … … 83 85 protected method _adjust_level {win} 84 86 87 private variable _done 0 88 private variable _tree "" 89 private variable _saved 90 private variable _name "" 91 private variable _revision 0; # Tool revision 85 92 private variable _tool "" ;# belongs to this tool 86 93 private variable _appName "" ;# Name of application … … 94 101 private variable _plotlist "" ;# items currently being plotted 95 102 private variable _lastPlot 96 private common job ;# array var used for blt::bgexec jobs97 103 private variable _uq_active 0 ;# a UQ variables has been used 98 104 private variable _wait_uq 0 105 private common job ;# array var used for blt::bgexec jobs 106 107 private method BuildQuestionDialog { popup } 108 private method BuildSimulationTable { w } 109 private method Cancel {} 110 private method CheckSimsetDetails {} 111 private method CleanName { name } 112 private method CreateSharedPath { path } 113 private method EditSimset {} 114 private method ExportFile { src msgFile } 115 private method ExportURL { appName installdir } 116 private method FindSimsetsForApp { appName } 117 private method GetSimset { name } 118 private method InstallSharedFile { installdir file } 119 private method LoadSimulations { runfiles } 120 private method Ok {} 121 private method OverwriteSaveFile {} 122 private method PostMenu { menu } 123 private method ReadSimsetFile { fileName } 124 private method Save {} 125 private method SaveSimulations {} 126 private method SelectSimsetForDeletion {} 127 private method SelectSimsetForLoading {} 128 private method SelectSimsetNameAndSave {} 129 private method SelectSimsetToShare {} 130 private method WriteSimsetFile { appName fileName share } 99 131 } 100 132 … … 108 140 itcl::body Rappture::Analyzer::constructor {tool args} { 109 141 set _tool $tool 142 set _tree [blt::tree create] 110 143 111 144 # use this to store all simulation results … … 149 182 150 183 # if there's a hub url, then add "About" and "Questions" links 151 set _appName [$_tool xml get tool.id] 184 global rapptureInfo 185 if { $rapptureInfo(appName) == "" } { 186 set _appName [$_tool xml get "tool.id"] 187 } else { 188 set _appName $rapptureInfo(appName) 189 } 190 set num [$_tool xml get "tool.version.application.revision"] 191 if { $num == "" } { 192 set num 0 193 } 194 set _revision $num 152 195 set url [Rappture::Tool::resources -huburl] 153 if {"" != $url && "" != $_appName} { 154 itk_component add hubcntls { 155 frame $itk_component(simbg).hubcntls 156 } { 157 usual 158 rename -background -simcontrolcolor simControlColor Color 159 } 160 pack $itk_component(hubcntls) -side right -padx 4 161 162 itk_component add icon { 163 label $itk_component(hubcntls).icon -image [Rappture::icon ask] \ 164 -highlightthickness 0 165 } { 166 usual 167 ignore -highlightthickness 168 rename -background -simcontrolcolor simControlColor Color 169 } 170 pack $itk_component(icon) -side left 171 172 itk_component add about { 173 button $itk_component(hubcntls).about -text "About this tool" \ 174 -command [list Rappture::filexfer::webpage \ 175 "$url/tools/$_appName"] 176 } { 177 usual 178 ignore -font 179 rename -background -simcontrolcolor simControlColor Color 180 rename -highlightbackground -simcontrolcolor simControlColor Color 181 } 182 pack $itk_component(about) -side top -anchor w 183 184 itk_component add questions { 185 button $itk_component(hubcntls).questions -text Questions? \ 186 -command [list Rappture::filexfer::webpage \ 187 "$url/resources/$_appName/questions"] 188 } { 189 usual 190 ignore -font 191 rename -background -simcontrolcolor simControlColor Color 192 rename -highlightbackground -simcontrolcolor simControlColor Color 193 } 194 pack $itk_component(questions) -side top -anchor w 195 } 196 196 197 itk_component add hubcntls { 198 frame $itk_component(simbg).hubcntls 199 } { 200 usual 201 rename -background -simcontrolcolor simControlColor Color 202 } 203 pack $itk_component(hubcntls) -side right -padx 4 204 205 itk_component add help { 206 menubutton $itk_component(hubcntls).help \ 207 -image [Rappture::icon hamburger_menu] \ 208 -highlightthickness 0 \ 209 -menu $itk_component(hubcntls).help.menu 210 } { 211 usual 212 ignore -highlightthickness 213 rename -background -simcontrolcolor simControlColor Color 214 } 215 pack $itk_component(help) -side left 216 buildMenu $itk_component(help).menu $url $_appName 217 197 218 itk_component add simstatus { 198 219 text $itk_component(simbg).simstatus -borderwidth 0 \ … … 399 420 # ---------------------------------------------------------------------- 400 421 itcl::body Rappture::Analyzer::simulate {args} { 401 #puts "simulate args='$args'"402 422 403 423 set uq [$_tool get_uq -uq_type smolyak -uq_args 2] … … 426 446 # check to see if simulation is really needed 427 447 $_tool sync 428 if {[$_resultset contains [$_tool xml object]] 429 &&![string equal $_control "manual-resim"]} {448 if {[$_resultset contains [$_tool xml object]] && 449 ![string equal $_control "manual-resim"]} { 430 450 # not needed -- show results and return 431 451 $itk_component(notebook) current analyze … … 518 538 # check to see if simulation is really needed 519 539 $_tool sync 520 if {![$_resultset contains [$_tool xml object]] 521 ||[string equal $_control "manual-resim"]} {540 if {![$_resultset contains [$_tool xml object]] || 541 [string equal $_control "manual-resim"]} { 522 542 # if control mode is "auto", then simulate right away 523 543 if {[string match auto* $_control]} { … … 1110 1130 # Scan through and pick out any =RAPPTURE-PROGRESS=> messages first. 1111 1131 # 1112 1113 while {[regexp -indices \ 1114 {=RAPPTURE-PROGRESS=> *([-+]?[0-9]+) +([^\n]*)(\n|$)} $message \ 1115 match percent mesg]} { 1132 set pattern {=RAPPTURE-PROGRESS=> *([-+]?[0-9]+) +([^\n]*)(\n|$)} 1133 while {[regexp -indices $pattern $message match percent mesg]} { 1116 1134 1117 1135 foreach {i0 i1} $percent break … … 1155 1173 # 1156 1174 $itk_component(runinfo) configure -state normal 1157 1158 while {[regexp -indices \ 1159 {=RAPPTURE-([a-zA-Z]+)=>([^\n]*)(\n|$)} $message \ 1160 match type mesg]} { 1161 1175 set pattern {=RAPPTURE-([a-zA-Z]+)=>([^\n]*)(\n|$)} 1176 while {[regexp -indices $pattern $message match type mesg]} { 1162 1177 foreach {i0 i1} $match break 1163 1178 set first [string range $message 0 [expr {$i0-1}]] … … 1202 1217 set name [$itk_component(viewselector) value] 1203 1218 if {[info exists _label2desc($name)] && 1204 1219 [string length $_label2desc($name)] > 0} { 1205 1220 append tip "$_label2desc($name)\n\n" 1206 1221 } … … 1470 1485 continue 1471 1486 } 1472 if 0 {1473 # Recurse over all child nodes.1474 _trajToSequence $xmlobj $current1475 }1476 1487 } 1477 1488 } … … 1498 1509 _fixNotebook 1499 1510 } 1511 1512 itcl::body Rappture::Analyzer::PostMenu { m } { 1513 if { [FindSimsetsForApp $_appName] == 0 } { 1514 $m entryconfigure "Load Simulations" -state disable 1515 $m entryconfigure "Share Simulations" -state disable 1516 $m entryconfigure "Delete Simulations" -state disabled 1517 } else { 1518 $m entryconfigure "Load Simulations" -state normal 1519 $m entryconfigure "Share Simulations" -state normal 1520 $m entryconfigure "Delete Simulations" -state normal 1521 } 1522 if { [$_resultset size] == 0 } { 1523 $m entryconfigure "Save Simulations" -state disabled 1524 } else { 1525 $m entryconfigure "Save Simulations" -state normal 1526 } 1527 } 1528 1529 # 1530 # Build Help menu 1531 # 1532 itcl::body Rappture::Analyzer::buildMenu { m url appName } { 1533 menu $m \ 1534 -tearoff 0 \ 1535 -postcommand [itcl::code $this PostMenu $m] 1536 if { $appName == "" || $url == "" } { 1537 set state disabled 1538 } else { 1539 set state normal 1540 } 1541 set webcmd Rappture::filexfer::webpage 1542 set group "app-$_appName" 1543 if { [info exists env(SESSION)] } { 1544 set referer "&referrer=$url/tools/$appName/session?sess=$env(SESSION)" 1545 } else { 1546 set referer "" 1547 } 1548 $m add command -label "About this tool" \ 1549 -command [list $webcmd "$url/tools/$appName"] \ 1550 -state $state 1551 $m add command -label "Questions?" \ 1552 -command [list $webcmd "$url/resources/$_appName/questions"] \ 1553 -state $state 1554 $m add command -label "Tickets" -state $state \ 1555 -command [list $webcmd "$url/feedback/report_problems?group=$group$referer"] 1556 $m add command -label "Wish List" -state disabled 1557 $m add separator 1558 $m add command -label "Save Simulations" \ 1559 -command [itcl::code $this SelectSimsetNameAndSave] \ 1560 -state $state 1561 $m add command -label "Load Simulations" \ 1562 -command [itcl::code $this SelectSimsetForLoading] \ 1563 -state $state 1564 $m add command -label "Delete Simulations" \ 1565 -command [itcl::code $this SelectSimsetForDeletion] \ 1566 -state $state 1567 $m add command -label "Share Simulations" \ 1568 -command [itcl::code $this SelectSimsetToShare] \ 1569 -state $state 1570 return $m 1571 } 1572 1573 itcl::body Rappture::Analyzer::BuildSimulationTable { top } { 1574 # All weirdness is due to the Resultset object. 1575 1576 # First create nodes for each simulation. The node label is the 1577 # simulation number (such as #1, #2, etc). 1578 eval $_tree delete 0 1579 set labels "selected simnum" 1580 foreach {name index} [$_resultset diff values simnum] { 1581 set node [$_tree insert 0 -label $name] 1582 $_tree set $node "simnum" $name 1583 set index2name($index) $name 1584 1585 } 1586 # Next fill in the xmlobj associated with each simulation. We assume 1587 # that the order is the the same as the simulation number. 1588 set index 0 1589 foreach {xmlobj dummy} [$_resultset diff values xmlobj] { 1590 set node [$_tree findchild 0 $index2name($index)] 1591 set runfile [$xmlobj get output.filename] 1592 set version [$xmlobj get output.version] 1593 $_tree set $node \ 1594 "selected" 1 "xmlobj" $xmlobj "runfile" $runfile "version" $version 1595 incr index 1596 } 1597 # Finally for each different input, for each simulation add the 1598 # label and value for the specific input. 1599 foreach name [$_resultset diff names] { 1600 # Ignore non-input names. 1601 if { $name == "xmlobj" || $name == "simnum" } { 1602 continue 1603 } 1604 foreach node [$_tree children 0] { 1605 set xmlobj [$_tree get $node xmlobj] 1606 set label [$xmlobj get $name.about.label] 1607 set value [$xmlobj get $name.current] 1608 if { [$_tree exists $node $label] } { 1609 puts stderr "This can't be: $label already exists in $node" 1610 } 1611 if { [lsearch $labels $label] < 0 } { 1612 lappend labels $label 1613 } 1614 $_tree set $node $label $value 1615 } 1616 } 1617 frame $top 1618 set tv $top.tv 1619 blt::treeview $top.tv -tree $_tree \ 1620 -height 1i \ 1621 -xscrollcommand [list $top.xs set] \ 1622 -yscrollcommand [list $top.ys set] \ 1623 -font "Arial 10" 1624 scrollbar $top.xs -orient horizontal -command "$tv xview" 1625 scrollbar $top.ys -orient vertical -command "$tv yview" 1626 1627 eval $tv column insert end $labels 1628 $tv style checkbox checkbox -showvalue no 1629 $tv column configure simnum -title "Simulation" 1630 $tv column configure selected -title "Save" -style checkbox \ 1631 -width .5i -edit yes 1632 $tv column configure treeView -hide yes 1633 blt::table $top \ 1634 0,0 $top.tv -fill both \ 1635 0,1 $top.ys -fill y \ 1636 1,0 $top.xs -fill x 1637 blt::table configure $top r* c* -resize none 1638 blt::table configure $top r0 c0 -resize both 1639 } 1640 1641 itcl::body Rappture::Analyzer::CleanName { name } { 1642 regsub -all {/} $name {_} name 1643 return $name 1644 } 1645 1646 # 1647 # Get the results and display them in a table. 1648 # 1649 # Use the table to omit specific results 1650 # Use file chooser to save to specific 1651 itcl::body Rappture::Analyzer::SelectSimsetNameAndSave {} { 1652 if { [EditSimset] } { 1653 set name [CleanName $_saved(Name)] 1654 set saveDir [file join ~/data/saved $_appName $name] 1655 set saveDir [file normalize $saveDir] 1656 file mkdir $saveDir 1657 set fileName [file join $saveDir $name.sav] 1658 if { [file exists $fileName] } { 1659 if { ![OverwriteSaveFile] } { 1660 return 1661 } 1662 } 1663 WriteSimsetFile $_appName $fileName 0 1664 } 1665 } 1666 1667 # 1668 # Get the results and display them in a table. 1669 # 1670 # Use the table to omit specific results 1671 # Use file chooser to save to specific 1672 itcl::body Rappture::Analyzer::SelectSimsetToShare {} { 1673 if { [GetSimset "share"] } { 1674 global env 1675 set name [CleanName $_saved(Name)] 1676 set shareDir [file join /data/tools/shared $env(USER) $_appName $name] 1677 if { [catch { 1678 CreateSharedPath $shareDir 1679 } errs] != 0 } { 1680 puts stderr errs=$errs 1681 return 1682 } 1683 set fileName [file join $shareDir $name.sav] 1684 if { [file exists $fileName] } { 1685 if { ![OverwriteSaveFile] } { 1686 return 1687 } 1688 } 1689 WriteSimsetFile $_appName $fileName 1 1690 ExportURL $_appName $shareDir 1691 } 1692 } 1693 1694 # 1695 # Checks editor widgets to see if the name and description have been 1696 # set. If this is so it enables the save button in the editor. 1697 # 1698 itcl::body Rappture::Analyzer::CheckSimsetDetails {} { 1699 set popup .savesimset 1700 if { ![winfo exists $popup] } { 1701 return 1702 } 1703 set inner [$popup component inner] 1704 set name [string trim [$inner.name get]] 1705 set desc [string trim [$inner.desc get 0.0 end]] 1706 $inner.controls.save configure -state disabled 1707 if { $name == "" || $desc == "" } { 1708 return 1709 } 1710 $inner.controls.save configure -state normal 1711 } 1712 1713 # 1714 # Gathers all the information from the simset editor into the _saved array 1715 # 1716 itcl::body Rappture::Analyzer::SaveSimulations {} { 1717 set popup .savesimset 1718 if { ![winfo exists $popup] } { 1719 return 1720 } 1721 set inner [$popup component inner] 1722 array unset _saved 1723 set name [string trim [$inner.name get]] 1724 set desc [string trim [$inner.desc get 0.0 end]] 1725 set _saved(Application) $_appName 1726 set _saved(Revision) $_revision 1727 set _saved(Date) [clock format [clock seconds]] 1728 set _saved(Name) $name 1729 set _saved(Description) $desc 1730 set files {} 1731 foreach node [$_tree children root] { 1732 set fileName [$_tree get $node runfile] 1733 lappend files $fileName 1734 } 1735 set _saved(Files) $files 1736 set _done 1 1737 } 1738 1739 itcl::body Rappture::Analyzer::Cancel {} { 1740 set _done 0 1741 } 1742 1743 itcl::body Rappture::Analyzer::Ok {} { 1744 set popup .selectsimset 1745 if { ![winfo exists $popup] } { 1746 return 1747 } 1748 set inner [$popup component inner] 1749 set tv $inner.tv 1750 if { ![$tv selection present] } { 1751 return 1752 } 1753 set node [$tv curselection] 1754 array unset _saved 1755 array set _saved [$_tree get $node] 1756 set saveDir [file dirname $_saved(FileName)] 1757 set files {} 1758 foreach file $_saved(Files) { 1759 if { [file pathtype $file] == "relative" } { 1760 set file [file join $saveDir $file] 1761 } 1762 lappend files $file 1763 } 1764 set _saved(Files) $files 1765 set _done 1 1766 } 1767 1768 # 1769 # WriteSimsetFile -- 1770 # 1771 # Write the .sav file and the runfiles in the 1772 # ~/data/saved/$_appName/$name 1773 # directory. 1774 # The run files will be in the same directory as the .sav file. 1775 # For example, if the simset file is /path/to/appName/myName/myName.sav, 1776 # the runfile directory is /path/to/appName/myName. 1777 # 1778 itcl::body Rappture::Analyzer::WriteSimsetFile { appName fileName share } { 1779 set saveDir [file dirname $fileName] 1780 if { [file exists $saveDir] } { 1781 file delete -force $saveDir 1782 } 1783 if { [catch { 1784 if { $share } { 1785 CreateSharedPath $saveDir 1786 } else { 1787 file mkdir $saveDir 1788 } 1789 set f [open $fileName "w"] 1790 puts $f [list "Name" $_saved(Name)] 1791 puts $f [list "Description" $_saved(Description)] 1792 puts $f [list "Date" $_saved(Date)] 1793 global env 1794 puts $f [list "Creator" $env(USER)] 1795 puts $f [list "Application" $_saved(Application)] 1796 puts $f [list "Revision" $_saved(Revision)] 1797 set runfiles "" 1798 foreach file $_saved(Files) { 1799 set tail [file tail $file] 1800 set dest [file join $saveDir $tail] 1801 if { $share } { 1802 InstallSharedFile $saveDir $file 1803 } else { 1804 file copy -force $file $dest 1805 } 1806 lappend runfiles $tail 1807 } 1808 puts $f [list "Files" $runfiles] 1809 close $f 1810 if { $share } { 1811 file attributes $fileName -permissions o+r,g+rw 1812 } 1813 } errs] != 0 } { 1814 global errorInfo 1815 puts stderr "errs=$errs errorInfo=$errorInfo" 1816 } 1817 } 1818 1819 itcl::body Rappture::Analyzer::EditSimset {} { 1820 set popup .savesimset 1821 if { [winfo exists $popup] } { 1822 destroy $popup 1823 } 1824 # Create a popup for the print dialog 1825 Rappture::Balloon $popup -title "Save set of simulations..." 1826 set inner [$popup component inner] 1827 1828 label $inner.name_l -text "Simulation Set Name" 1829 entry $inner.name -background white 1830 label $inner.desc_l -text "Simulation Set Description" -height 5 1831 text $inner.desc -background white 1832 label $inner.select_l -text "Selected Simulations" 1833 BuildSimulationTable $inner.select 1834 frame $inner.controls 1835 bind $inner.desc <KeyPress> [itcl::code $this CheckSimsetDetails] 1836 bind $inner.name <KeyPress> [itcl::code $this CheckSimsetDetails] 1837 bind $inner.desc <Motion> [itcl::code $this CheckSimsetDetails] 1838 bind $inner.name <Motion> [itcl::code $this CheckSimsetDetails] 1839 button $inner.controls.cancel -text "Cancel" \ 1840 -command [itcl::code $this Cancel] 1841 button $inner.controls.save -text "Save" \ 1842 -command [itcl::code $this SaveSimulations] 1843 blt::table $inner.controls \ 1844 0,0 $inner.controls.cancel \ 1845 0,1 $inner.controls.save 1846 1847 blt::table $inner \ 1848 0,0 $inner.name_l -anchor ne \ 1849 0,1 $inner.name -fill x \ 1850 1,0 $inner.desc_l -anchor ne \ 1851 1,1 $inner.desc -fill both \ 1852 2,0 $inner.select_l -anchor ne \ 1853 2,1 $inner.select -fill both \ 1854 3,1 $inner.controls -fill x 1855 blt::table configure $inner r1 -height 1i 1856 blt::table configure $inner r2 -pad 20 1857 $popup configure \ 1858 -deactivatecommand [itcl::code $this Cancel] 1859 1860 set inner [$popup component inner] 1861 if {[$_resultset size] > 1} { 1862 blt::table $inner \ 1863 2,0 $inner.select_l -anchor ne \ 1864 2,1 $inner.select -fill both 1865 } else { 1866 blt::table forget $inner.select $inner.select_l 1867 } 1868 CheckSimsetDetails 1869 update 1870 # Activate the popup and call for the output. 1871 $popup activate $itk_component(help) below 1872 Cancel 1873 tkwait variable [itcl::scope _done] 1874 set doSave $_done 1875 $popup deactivate 1876 return $doSave 1877 } 1878 1879 1880 itcl::body Rappture::Analyzer::ReadSimsetFile { fileName } { 1881 if { [catch { 1882 set f [open $fileName "r"] 1883 set contents [read $f] 1884 close $f 1885 array set _saved $contents 1886 } errs] != 0 } { 1887 return 0 1888 } 1889 if { ![info exists _saved(Files)] } { 1890 return 0 1891 } 1892 set saveDir [file dirname $fileName] 1893 foreach file $_saved(Files) { 1894 if { [file pathtype $file] == "relative" } { 1895 set file [file join $saveDir $file] 1896 } 1897 if { ![file readable $file] } { 1898 puts stderr "runfile $file isn't readable" 1899 return 0 1900 } 1901 } 1902 set _saved(FileName) $fileName 1903 return 1 1904 } 1905 1906 # 1907 # Run files can be either explicitly named with their absolute or 1908 # relative path. If the path is relative it is assumed the parent 1909 # directory is relative to the simset file. 1910 # 1911 # /my/path/to/myfile.sav 1912 # /my/path/to/myfile/runfiles... 1913 # 1914 itcl::body Rappture::Analyzer::LoadSimulations { files } { 1915 set loadobjs {} 1916 set saveDir [file dirname $_saved(FileName)] 1917 foreach runfile $files { 1918 if { [file pathtype $runfile] == "relative" } { 1919 set runfile [file join $saveDir $runfile] 1920 } 1921 if { ![file exists $runfile] } { 1922 puts stderr "can't find run: \"$runfile\"" 1923 continue 1924 } 1925 set status [catch {Rappture::library $runfile} result] 1926 lappend loadobjs $result 1927 } 1928 clear 1929 foreach runobj $loadobjs { 1930 load $runobj 1931 } 1932 configure -notebookpage analyze 1933 global win 1934 $win.pager configure -nosim 1 1935 $win.pager current analyzer 1936 $win.pager configure -nosim 0 1937 } 1938 1939 # 1940 # Delete selected simulation set. 1941 # 1942 itcl::body Rappture::Analyzer::SelectSimsetForDeletion {} { 1943 if { [FindSimsetsForApp $_appName] == 0 } { 1944 return 1945 } 1946 if { [GetSimset "delete"] } { 1947 set saveDir [file dirname $_saved(FileName)] 1948 file delete -force $saveDir 1949 } 1950 } 1951 1952 # 1953 # Find all .sav files for an application and load them into the tree. 1954 # 1955 itcl::body Rappture::Analyzer::FindSimsetsForApp { appName } { 1956 if { $appName == "" } { 1957 puts stderr "No application name found" 1958 return 0 1959 } 1960 $_tree delete 0 1961 foreach fileName [glob -nocomplain ~/data/saved/$appName/*/*.sav] { 1962 if { [ReadSimsetFile $fileName] } { 1963 if { $_revision > 0 && [info exists _saved(Revision)] && 1964 $_revision != $_saved(Revision) } { 1965 continue; # Revision doesn't match. 1966 } 1967 $_tree insert 0 -label $_saved(Name) -data [array get _saved] 1968 } 1969 } 1970 return [$_tree degree 0] 1971 } 1972 1973 # 1974 # Create dialog to select a simset from the currently available simsets. 1975 # 1976 itcl::body Rappture::Analyzer::GetSimset { name } { 1977 set popup .selectsimset 1978 if { [winfo exists $popup] } { 1979 destroy $popup 1980 } 1981 # Create a popup for the print dialog 1982 set title [string tolower $name] 1983 Rappture::Balloon $popup -title "Select set of simulations to $title..." 1984 set inner [$popup component inner] 1985 1986 set tv $inner.tv 1987 blt::treeview $inner.tv -tree $_tree \ 1988 -height 1i \ 1989 -width 5i \ 1990 -xscrollcommand [list $inner.xs set] \ 1991 -yscrollcommand [list $inner.ys set] \ 1992 -font "Arial 10" 1993 scrollbar $inner.xs -orient horizontal -command "$tv xview" 1994 scrollbar $inner.ys -orient vertical -command "$tv yview" 1995 frame $inner.controls 1996 1997 $tv column insert end "Name" "Description" "Date" "Creator" 1998 $tv column configure treeView -hide yes 1999 blt::table $inner \ 2000 0,0 $inner.tv -fill both \ 2001 0,1 $inner.ys -fill y \ 2002 1,0 $inner.xs -fill x 2003 blt::table configure $inner r* c* -resize none 2004 blt::table configure $inner r0 c0 -resize both 2005 2006 button $inner.controls.cancel -text "Cancel" \ 2007 -command [itcl::code $this Cancel] 2008 set title [string totitle $name] 2009 button $inner.controls.save -text $title \ 2010 -command [itcl::code $this Ok] 2011 blt::table $inner.controls \ 2012 0,0 $inner.controls.cancel \ 2013 0,1 $inner.controls.save 2014 2015 blt::table $inner \ 2016 0,0 $inner.tv -fill both \ 2017 0,1 $inner.ys -fill y \ 2018 1,0 $inner.xs -fill x \ 2019 3,0 $inner.controls -fill x -cspan 2 2020 blt::table configure $inner r* c* -resize none 2021 blt::table configure $inner r0 c0 -resize both 2022 blt::table configure $inner r2 -height 0.1i 2023 2024 $popup configure \ 2025 -deactivatecommand [itcl::code $this Cancel] 2026 2027 $tv selection set [$_tree firstchild 0] 2028 set inner [$popup component inner] 2029 update 2030 # Activate the popup and call for the output. 2031 $popup activate $itk_component(help) below 2032 Cancel 2033 tkwait variable [itcl::scope _done] 2034 set result $_done 2035 $popup deactivate 2036 return $result 2037 } 2038 2039 itcl::body Rappture::Analyzer::SelectSimsetForLoading {} { 2040 if { [FindSimsetsForApp $_appName] == 0 } { 2041 return 2042 } 2043 if { [GetSimset "load"] } { 2044 LoadSimulations $_saved(Files) 2045 } 2046 } 2047 2048 itcl::body Rappture::Analyzer::reload { fileName } { 2049 if { [catch { 2050 ReadSimsetFile $fileName 2051 if { [llength $_saved(Files)] > 0 } { 2052 #StartSplashScreen 2053 LoadSimulations $_saved(Files) 2054 #HideSplashScreen 2055 } 2056 } errs] != 0 } { 2057 puts stderr "can't load \"$fileName\": errs=$errs" 2058 } 2059 } 2060 2061 itcl::body Rappture::Analyzer::BuildQuestionDialog { popup } { 2062 toplevel $popup -background grey92 -bd 2 -relief raised 2063 wm withdraw $popup 2064 wm overrideredirect $popup true 2065 set inner $popup 2066 # Create the print dialog widget and add it to the the balloon popup. 2067 label $popup.title -text " " \ 2068 -padx 10 -pady 10 \ 2069 -background grey92 2070 button $popup.yes -text "Yes" \ 2071 -highlightthickness 0 \ 2072 -bd 2 \ 2073 -command [itcl::code $this Save] 2074 button $popup.no -text "No" \ 2075 -highlightthickness 0 \ 2076 -bd 2 \ 2077 -command [itcl::code $this Cancel] 2078 blt::table $popup \ 2079 0,0 $popup.title -cspan 2 -fill x -pady 4 \ 2080 1,0 $popup.yes -width { 0 1i .6i } -pady 4 \ 2081 1,1 $popup.no -width { 0 1i .6i } -pady 4 2082 blt::table configure $popup r2 -height 0.125i 2083 } 2084 2085 itcl::body Rappture::Analyzer::Save {} { 2086 set _done 1 2087 } 2088 2089 itcl::body Rappture::Analyzer::OverwriteSaveFile {} { 2090 set popup .question 2091 if { ![winfo exists $popup] } { 2092 BuildQuestionDialog $popup 2093 } 2094 set text "Simulation set \"$_saved(Name)\" already exists. Overwrite?" 2095 $popup.title configure -text $text 2096 $popup.yes configure -text "Save" 2097 $popup.no configure -text "Cancel" 2098 set main [winfo toplevel $itk_component(help)] 2099 set pw [winfo reqwidth $popup] 2100 set ph [winfo reqheight $popup] 2101 set sw [winfo reqwidth $main] 2102 set sh [winfo reqheight $main] 2103 set rootx [winfo rootx $main] 2104 set rooty [winfo rooty $main] 2105 set x [expr $rootx + (($sw - $pw) / 2)] 2106 set y [expr $rooty + (($sh - $ph) / 2)] 2107 wm geometry $popup +$x+$y 2108 wm deiconify $popup 2109 update 2110 grab $popup 2111 # Activate the popup and call for the output. 2112 Cancel 2113 tkwait variable [itcl::scope _done] 2114 set doSave $_done 2115 grab release $popup 2116 destroy $popup 2117 return $doSave 2118 } 2119 2120 itcl::body Rappture::Analyzer::InstallSharedFile { installdir file } { 2121 set dst [file join $installdir [file tail $file]] 2122 file copy -force $file $dst 2123 file attributes $dst -permissions g+rw,o+r 2124 return $dst 2125 } 2126 2127 itcl::body Rappture::Analyzer::CreateSharedPath { path } { 2128 set dir "" 2129 foreach file [file split $path] { 2130 set dir [file join $dir $file] 2131 if { [file exists $dir] } { 2132 if { ![file isdirectory $dir] } { 2133 error "error in path \"$path\": \"$dir\" is not a directory." 2134 } 2135 } else { 2136 file mkdir $dir 2137 file attributes $dir -permissions g+rwx,o+rx 2138 } 2139 } 2140 } 2141 2142 itcl::body Rappture::Analyzer::ExportURL { appName installdir } { 2143 set fileName [file join $installdir url.txt] 2144 set name [file tail $installdir] 2145 set f [open $fileName "w"] 2146 puts $f "https://nanohub.org/tools/$appName/invoke?params=file(simset):$installdir/$name.sav\n" 2147 close $f 2148 file attributes $fileName -permissions g+rw,o+r 2149 if { [file exists /usr/bin/exportfile] } { 2150 set msgFile [file join $::Rappture::installdir export.html] 2151 ExportFile $fileName $msgFile 2152 } 2153 } 2154 2155 itcl::body Rappture::Analyzer::ExportFile { src msgFile } { 2156 set dstdir ~/.filexfer/exportfile 2157 file mkdir $dstdir 2158 set dst [file join $dstdir [file tail $src]] 2159 if { [file exists $dst] } { 2160 puts stderr "could be a problem: already waiting to export $dst" 2161 } 2162 file copy -force $src $dst 2163 # Now export the file. 2164 if { [catch { 2165 global exportFileVar 2166 set exportFileVar 0; # Kill any previous export. 2167 set mesg "Select file to export to desktop/laptop" 2168 update 2169 set cmd "/usr/bin/exportfile --delete $dst --timeout 3 " 2170 if { [file exists $msgFile] } { 2171 append cmd "--message $msgFile" 2172 } 2173 blt::bgexec exportFileVar /bin/sh -c $cmd & 2174 } errs] != 0 } { 2175 global errorInfo 2176 puts stderr "err: $errorInfo" 2177 file delete -force $dst 2178 } 2179 } 2180 -
trunk/gui/scripts/loader.tcl
r5659 r6473 38 38 39 39 private method SetDefaultValue { value } 40 private method EventuallySetDefaultValue { value } 40 41 41 42 private variable _owner "" ;# thing managing this control … … 246 247 set str [string trim [$_owner xml get $path.default]] 247 248 if { $str != "" } { 248 bind $itk_component(hull) <Map> [itcl::code $this SetDefaultValue $str]249 EventuallySetDefaultValue $str 249 250 } 250 251 } … … 285 286 $itk_component(combo) value $newval 286 287 return $newval 287 288 288 } elseif {[llength $args] != 0} { 289 289 error "wrong # args: should be \"value ?-check? ?newval?\"" … … 323 323 } 324 324 325 #326 # SetDefaultValue --327 #328 # Sets the designated default value for the loader. This must be done329 # after the entire application is assembled, otherwise the default330 # values set up by the loader will be overwritten by the various widgets331 # themselves when they try to set their default values.332 #333 # This is called from a <Map> event to the loader (combobox). This334 # will get trigger the first time the loader is displayed. The binding335 # is then removed.336 #337 325 itcl::body Rappture::Loader::SetDefaultValue { value } { 338 after idle [itcl::code $this value $value] 339 # We're done. Remove the binding. 340 bind $itk_component(hull) <Map> {} 326 $itk_component(combo) value $value 327 _newValue 328 } 329 # 330 # 331 # EventuallySetDefaultValue -- 332 # 333 # Sets the designated default value for the loader. This must be done 334 # after the entire application is assembled, otherwise the default values 335 # set up by the loader will be overwritten by the various widgets 336 # themselves when they try to set their default values. 337 # 338 itcl::body Rappture::Loader::EventuallySetDefaultValue { value } { 339 after 100 [itcl::code $this SetDefaultValue $value] 341 340 } 342 341 -
trunk/gui/scripts/main.tcl
r6022 r6473 94 94 list -load "" 95 95 value -input "" 96 value -simset "" 96 97 value -nosim 0 97 98 } … … 260 261 261 262 # 262 # Add a place for about/questionsin the breadcrumbs area of this pager.263 # Add a place for menu button in the breadcrumbs area of this pager. 263 264 # 264 265 set app [string trim [$tool xml get tool.id]] 265 266 set url [Rappture::Tool::resources -huburl] 266 if {"" != $url && "" != $app} { 267 set f [$win.pager component breadcrumbarea] 268 frame $f.hubcntls 269 pack $f.hubcntls -side right -padx 4 270 label $f.hubcntls.icon -image [Rappture::icon ask] -highlightthickness 0 271 pack $f.hubcntls.icon -side left 272 button $f.hubcntls.about -text "About this tool" -command " 273 [list Rappture::filexfer::webpage $url/tools/$app] 274 Rappture::Logger::log help about 275 " 276 pack $f.hubcntls.about -side top -anchor w 277 button $f.hubcntls.questions -text Questions? -command " 278 [list Rappture::filexfer::webpage $url/resources/$app/questions] 279 Rappture::Logger::log help questions 280 " 281 pack $f.hubcntls.questions -side top -anchor w 282 } 267 set crumbs [$win.pager component breadcrumbarea] 268 frame $crumbs.hubcntls 269 pack $crumbs.hubcntls -side right -padx 4 270 271 set m $crumbs.hubcntls.help.menu 272 menubutton $crumbs.hubcntls.help \ 273 -image [Rappture::icon hamburger_menu] \ 274 -highlightthickness 0 \ 275 -menu $m 276 pack $crumbs.hubcntls.help -side top -anchor w 283 277 284 278 # … … 339 333 340 334 $tool notify add analyzer * [list $f.analyze reset] 335 $f.analyze buildMenu $m $url $app 336 341 337 342 338 # ---------------------------------------------------------------------- … … 386 382 387 383 # load previous xml runfiles 384 update 388 385 if {[llength $params(-load)] > 0} { 389 386 foreach runobj $loadobjs { … … 398 395 } 399 396 $f.analyze configure -notebookpage analyze 397 $win.pager configure -nosim 1 400 398 $win.pager current analyzer 399 $win.pager configure -nosim 0 400 } elseif {$params(-simset) ne ""} { 401 $f.analyze reload $params(-simset) 401 402 } elseif {$params(-input) ne ""} { 402 403 $tool load $inputobj … … 407 408 408 409 foreach path [array names ::Rappture::parameters] { 410 if { $path == "simset" } { 411 continue; # Don't consider file(simset) 412 } 409 413 set fname $::Rappture::parameters($path) 410 if {[catch { 411 set fid [open $fname r] 412 set info [read $fid] 413 close $fid}] == 0} { 414 415 set w [$tool widgetfor $path] 416 if {$w ne ""} { 417 if {[catch {$w value [string trim $info]} result]} { 418 puts stderr "WARNING: bad tool parameter value for \"$path\"" 419 puts stderr " $result" 420 } 421 } else { 422 puts stderr "WARNING: can't find control for tool parameter: $path" 423 } 414 if { ![file exists $fname] } { 415 puts stderr "WARNING: tool parameters file \"$fname\" doesn't exist" 416 continue; # Can't find parameters file 417 } 418 if { ![file readable $fname] } { 419 puts stderr "WARNING: can't read tool parameters file \"$fname\"" 420 continue; # Can't read parameters file 421 } 422 set f [open $fname r] 423 set contents [read $f] 424 close $f 425 426 set w [$tool widgetfor $path] 427 if { $w == "" } { 428 puts stderr "WARNING: can't find control for tool parameter: $path" 429 continue; # Can't find rappture control for path 430 } 431 if {[catch {$w value [string trim $info]} result]} { 432 puts stderr "WARNING: bad tool parameter value for \"$path\"" 433 puts stderr " $result" 424 434 } 425 435 } -
trunk/gui/scripts/pager.tcl
r5659 r6473 67 67 private variable _page2info ;# maps page name => -frame,-title,-command 68 68 private variable _current "" ;# page currently shown 69 public variable nosim 0 69 70 } 70 71 … … 374 375 # invoke it now. 375 376 # 376 if {"" != $_current 377 &&[string length $_page2info($_current-command)] > 0} {377 if {"" != $_current && !$nosim && 378 [string length $_page2info($_current-command)] > 0} { 378 379 uplevel #0 $_page2info($_current-command) 379 380 } -
trunk/lang/tcl/scripts/task.tcl
r6296 r6473 19 19 20 20 itcl::class Rappture::Task { 21 private method CheckForCachedRunFile { driverFile } 22 private method CollectUQResults {} 23 private method ExecuteSimulationCommand { cmd } 24 private method GetCommand {} 25 private method GetDriverFile {} 26 private method GetSignal { signal } 27 private method GetSimulationCommand { driverFile } 28 private method GetUQErrors {} 29 private method GetUQSimulationCommand { driverFile } 30 private method GetUQTemplateFile {} 31 private method IsCacheable {} 32 private method LogCachedSimulationUsage {} 33 private method LogSimulationUsage {} 34 private method LogSubmittedSimulationUsage {} 35 private method SetCpuResourceLimit {} 36 21 37 public variable logger "" 22 38 public variable jobstats Rappture::Task::MiddlewareTime … … 35 51 public method save {xmlobj {name ""}} 36 52 37 protected method _mkdir {dir} 38 protected method _output {data} 39 protected method _log {args} 40 protected method _build_submit_cmd {cmd tfile params_file} 41 protected method _get_params {varlist uq_type uq_args} 42 private method GetSignal { signal } 53 protected method OnOutput {data} 54 protected method Log {args} 55 protected method BuildSubmitCommand {cmd tfile params_file} 56 protected method GetParamsForUQ {} 43 57 44 58 private variable _xmlobj "" ;# XML object with inputs/outputs 45 59 private variable _origxml "" ;# copy of original XML (for reset) 46 private variable _lastrun "" ;# name of last run file47 60 private variable _installdir "" ;# installation directory for this tool 48 61 private variable _outputcb "" ;# callback for tool output 49 private common job ;# array var used for blt::bgexec jobs50 62 private common jobnum 0 ;# counter for unique job number 51 63 private variable _uq 64 65 private variable _job 66 52 67 # get global resources for this tool session 53 68 public proc resources {{option ""}} 54 69 55 70 public common _resources 56 public proc setAppName {name} { set _resources(-appname) $name } 57 public proc setHubName {name} { set _resources(-hubname) $name } 58 public proc setHubURL {name} { set _resources(-huburl) $name } 59 public proc setSession {name} { set _resources(-session) $name } 60 public proc setJobPrt {name} { set _resources(-jobprotocol) $name } 61 public proc setResultDir {name} { set _resources(-resultdir) $name } 71 public proc setAppName {name} { set _resources(-appname) $name } 72 public proc setHubName {name} { set _resources(-hubname) $name } 73 public proc setHubURL {name} { set _resources(-huburl) $name } 74 public proc setSession {name} { set _resources(-session) $name } 75 public proc setJobPrt {name} { set _resources(-jobprotocol) $name } 76 public proc setResultDir {name} { set _resources(-resultdir) $name } 77 public proc setCacheHosts {name} { set _resources(-cachehosts) $name } 62 78 63 79 # default method for -jobstats control … … 74 90 session_token Rappture::Task::setSession \ 75 91 job_protocol Rappture::Task::setJobPrt \ 76 results_directory Rappture::Task::setResultDir 92 results_directory Rappture::Task::setResultDir \ 93 cache_hosts Rappture::Task::setCacheHosts 77 94 } 78 95 … … 94 111 } 95 112 set _installdir $installdir 113 package require http 114 package require tls 115 http::register https 443 [list ::tls::socket -tls1 1] 96 116 97 117 eval configure $args … … 137 157 foreach {path val} $args { 138 158 if {$path == "-uq_type"} { 139 set uq_type$val159 set _uq(type) $val 140 160 } elseif {$path == "-uq_args"} { 141 set uq_args$val161 set _uq(args) $val 142 162 } 143 163 } 144 164 #set varlist [$_xmlobj uq_get_vars] 145 165 foreach {varlist num} [$_xmlobj uq_get_vars] break 146 return [Rappture::UQ ::#auto $varlist $num $ uq_type $uq_args]166 return [Rappture::UQ ::#auto $varlist $num $_uq(type) $_uq(args)] 147 167 } 148 168 … … 173 193 174 194 # 175 # Make sure that we save the proper application name. 176 # Actually, the best place to get this information is 177 # straight from the "installtool" script, but just in 178 # case we have an older tool, we should insert the 195 # Make sure that we save the proper application name. Actually, the 196 # best place to get this information is straight from the "installtool" 197 # script, but just in case we have an older tool, we should insert the 179 198 # tool name from the resources config file. 180 199 # 181 if {[info exists _resources(-appname)] 182 && $_resources(-appname) ne "" 183 && [$_xmlobj get tool.name] eq ""} { 200 if {[info exists _resources(-appname)] && $_resources(-appname) ne "" && 201 [$_xmlobj get tool.name] eq ""} { 184 202 $_xmlobj put tool.name $_resources(-appname) 185 203 } … … 187 205 # if there are any args, use them to override parameters 188 206 set _outputcb "" 189 set uq_type""207 set _uq(type) "" 190 208 foreach {path val} $args { 191 209 if {$path == "-output"} { 192 210 set _outputcb $val 193 211 } elseif {$path == "-uq_type"} { 194 set uq_type$val212 set _uq(type) $val 195 213 } elseif {$path == "-uq_args"} { 196 set uq_args$val214 set _uq(args) $val 197 215 } else { 198 216 $_xmlobj put $path.current $val … … 200 218 } 201 219 202 foreach item {control output error} { set job($item) "" } 203 220 # Initialize job array variables 221 array set _job { 222 control "" 223 exitcode 0 224 mesg "" 225 runfile "" 226 stderr "" 227 stdout "" 228 success 0 229 xmlobj "" 230 } 231 232 SetCpuResourceLimit 233 set driverFile [GetDriverFile] 234 set cached 0 235 if { [IsCacheable] } { 236 puts stderr "Cache checking: [time { 237 set cached [CheckForCachedRunFile $driverFile] 238 } ]" 239 puts stderr "checking cache=$cached" 240 } 241 if { !$cached } { 242 if { $_uq(type) != "" } { 243 set _uq(tfile) [GetUQTemplateFile] 244 } 245 if { $_uq(type) == "" } { 246 set cmd [GetSimulationCommand $driverFile] 247 } else { 248 set cmd [GetUQSimulationCommand $driverFile] 249 } 250 if { $cmd == "" } { 251 puts stderr "cmd is empty" 252 append mesg "There is no command specified by\n\n" 253 append mesg " <command>\n" 254 append mesg " </command>\n\n" 255 append mesg "in the tool.xml file." 256 return [list 1 $mesg] 257 } 258 Rappture::rusage mark 259 if { ![ExecuteSimulationCommand $cmd] } { 260 return [list 1 $_job(mesg)] 261 } 262 if { [resources -jobprotocol] == "submit" } { 263 LogSubmittedSimulationUsage 264 } else { 265 LogSimulationUsage 266 } 267 } else { 268 LogCachedSimulationUsage 269 } 270 if { $_job(success) } { 271 file delete -force -- $driverFile 272 Log run finished 273 return [list 0 $_job(xmlobj)] 274 } else { 275 # See if the job was aborted. 276 if {[regexp {^KILLED} $_job(control)]} { 277 Log run aborted 278 return [list 1 "ABORT"] 279 } 280 Log run failed [list 0 $_job(mesg)] 281 return [list 1 $_job(mesg)] 282 } 283 } 284 285 # ---------------------------------------------------------------------- 286 # Turn the command string from tool.xml into the proper syntax to use 287 # with a submit parameter sweep with a temlate file. Proper quoting 288 # of the template file is necessary to prevent submit from being too smart 289 # and converting it to a full pathname. 290 # ---------------------------------------------------------------------- 291 itcl::body Rappture::Task::BuildSubmitCommand {cmd tfile params_file} { 292 set quote_next 0 293 set newcmd "submit --progress submit --runName=puq -l -i @:$tfile -d $params_file" 294 set cmds [split $cmd " "] 295 for {set i 0} {$i < [llength $cmds]} {incr i} { 296 set arg [lindex $cmds $i] 297 if {$quote_next == 1} { 298 set nc [string range $arg 0 0] 299 if {$nc != "\""} { 300 set arg "\"\\\"$arg\\\"\"" 301 } 302 } 303 if {$arg == "--eval"} { 304 set quote_next 1 305 } else { 306 set quote_next 0 307 } 308 if {$arg == "@driver"} { 309 set arg "\"\\\"$tfile\\\"\"" 310 } 311 append newcmd " " $arg 312 } 313 regsub -all @driver $newcmd $tfile newcmd 314 return $newcmd 315 } 316 317 # ---------------------------------------------------------------------- 318 # USAGE: abort 319 # 320 # Clients use this during a "run" to abort the current job. 321 # Kills the job and forces the "run" method to return. 322 # ---------------------------------------------------------------------- 323 itcl::body Rappture::Task::abort {} { 324 Log run abort 325 set _job(control) "abort" 326 } 327 328 # ---------------------------------------------------------------------- 329 # USAGE: reset 330 # 331 # Resets all input values to their defaults. Sometimes used just 332 # before a run to reset to a clean state. 333 # ---------------------------------------------------------------------- 334 itcl::body Rappture::Task::reset {} { 335 $_xmlobj copy "" from $_origxml "" 336 foreach path [Rappture::entities -as path $_xmlobj input] { 337 if {[$_xmlobj element -as type $path.default] ne ""} { 338 set defval [$_xmlobj get $path.default] 339 $_xmlobj put $path.current $defval 340 } 341 } 342 } 343 344 # ---------------------------------------------------------------------- 345 # USAGE: xml <subcommand> ?<arg> <arg> ...? 346 # USAGE: xml object 347 # 348 # Used by clients to manipulate the underlying XML data for this 349 # tool. The <subcommand> can be any operation supported by a 350 # Rappture::library object. Clients can also request the XML object 351 # directly by using the "object" subcommand. 352 # ---------------------------------------------------------------------- 353 itcl::body Rappture::Task::xml {args} { 354 if {"object" == $args} { 355 return $_xmlobj 356 } 357 return [eval $_xmlobj $args] 358 } 359 360 # ---------------------------------------------------------------------- 361 # USAGE: save <xmlobj> ?<filename>? 362 # 363 # Used by clients to save the contents of an <xmlobj> representing 364 # a run out to the given file. If <filename> is not specified, then 365 # it uses the -resultsdir and other settings to do what Rappture 366 # would normally do with the output. 367 # ---------------------------------------------------------------------- 368 itcl::body Rappture::Task::save {xmlobj {filename ""}} { 369 if {$filename eq ""} { 370 371 # If there's a results_directory defined in the resources file, 372 # then move the run.xml file there for storage. 373 374 set rdir "" 375 if {$resultdir eq "@default"} { 376 if {[info exists _resources(-resultdir)]} { 377 set rdir $_resources(-resultdir) 378 } else { 379 global rapptureInfo 380 set rdir $rapptureInfo(cwd) 381 } 382 } elseif {$resultdir ne ""} { 383 set rdir $resultdir 384 } 385 386 # use the runfile name generated by the last run 387 if {$_job(runfile) ne ""} { 388 set filename [file join $rdir $_job(runfile)] 389 } else { 390 set filename [file join $rdir run.xml] 391 } 392 } 393 394 # add any last-minute metadata 395 $xmlobj put output.time [clock format [clock seconds]] 396 397 $xmlobj put tool.version.rappture.version $::Rappture::version 398 $xmlobj put tool.version.rappture.revision $::Rappture::build 399 $xmlobj put output.filename $filename 400 $xmlobj put output.version $Rappture::version 401 402 if {[info exists ::tcl_platform(user)]} { 403 $xmlobj put output.user $::tcl_platform(user) 404 } 405 406 # save the output 407 set rdir [file dirname $filename] 408 file mkdir $rdir 409 410 set fid [open $filename w] 411 puts $fid "<?xml version=\"1.0\"?>" 412 puts $fid [$xmlobj xml] 413 close $fid 414 415 Log output saved in $filename 416 } 417 418 # ---------------------------------------------------------------------- 419 # USAGE: OnOutput <data> 420 # 421 # Used internally to send each bit of output <data> coming from the 422 # tool onto the caller, so the user can see progress. 423 # ---------------------------------------------------------------------- 424 itcl::body Rappture::Task::OnOutput {data} { 425 if {[string length $_outputcb] > 0} { 426 uplevel #0 $_outputcb [list $data] 427 } 428 } 429 430 # ---------------------------------------------------------------------- 431 # USAGE: Log <cmd> <arg> <arg> ... 432 # 433 # Used internally to log interesting events during the run. If the 434 # -logger option is set (to Rappture::Logger::log, or something like 435 # that), then the arguments to this method are passed along to the 436 # logger and written out to a log file. Logging is off by default, 437 # so this method does nothing unless -logger is set. 438 # ---------------------------------------------------------------------- 439 itcl::body Rappture::Task::Log {args} { 440 if {[string length $logger] > 0} { 441 uplevel #0 $logger [list $args] 442 } 443 } 444 445 # ---------------------------------------------------------------------- 446 # USAGE: MiddlewareTime <key> <value> ... 447 # 448 # Used as the default method for reporting job status information. 449 # Implements the old HUBzero method of reporting job status info to 450 # stderr, which can then be picked up by the tool session container. 451 # Most tools use the "submit" command, which talks directly to a 452 # database to log job information, so this isn't really needed. But 453 # it doesn't hurt to have this and it can be useful in some cases. 454 # ---------------------------------------------------------------------- 455 itcl::body Rappture::Task::MiddlewareTime {args} { 456 set line "MiddlewareTime:" 457 foreach {key val} $args { 458 append line " $key=$val" 459 } 460 puts stderr $line 461 } 462 463 itcl::body Rappture::Task::IsCacheable {} { 464 if { ![info exists _resources(-cachehosts)] || 465 $_resources(-cachehosts) == "" } { 466 puts stderr cachehosts=[info exists _resources(-cachehosts)] 467 return 0 468 } 469 if 0 { 470 set state [$_xmlobj get "tool.cache"] 471 puts stderr "cache tag is \"$state\"" 472 if { $state == "" } { 473 return 0 474 } 475 } else { 476 set state 1 477 } 478 if { ![string is boolean $state] } { 479 return 0 480 } 481 return $state 482 } 483 484 # 485 # Send the list of parameters to a python program so it can call PUQ 486 # and get a CSV file containing the parameter values to use for the runs. 487 itcl::body Rappture::Task::GetParamsForUQ {} { 488 set pid [pid] 489 # puts "puq.sh get_params $pid $_uq(varlist) $_uq(type) $_uq(args)" 490 if {[catch { 491 exec puq.sh get_params $pid $_uq(varlist) $_uq(type) $_uq(args) 492 } errs] != 0 } { 493 error "get_params.py failed: $errs\n[GetUQErrors]" 494 } 495 return "params${pid}.csv" 496 } 497 498 itcl::body Rappture::Task::SetCpuResourceLimit {} { 204 499 # Set limits for cpu time 205 500 set limit [$_xmlobj get tool.limits.cputime] … … 216 511 } 217 512 Rappture::rlimit set cputime $limit 218 219 # write out the driver.xml file for the tool 513 } 514 515 # Write out the driver.xml file for the tool 516 itcl::body Rappture::Task::GetDriverFile {} { 220 517 global rapptureInfo 221 set file [file join $rapptureInfo(cwd) "driver[pid].xml"] 222 set status [catch { 223 set fid [open $file w] 224 puts $fid "<?xml version=\"1.0\"?>" 225 puts $fid [$_xmlobj xml] 226 close $fid 227 } result] 228 229 if {$uq_type != ""} { 230 # Copy xml into a new file 231 set tfile "template[pid].xml" 232 set fid [open $tfile w] 233 puts $fid "<?xml version=\"1.0\"?>" 234 puts $fid [$_xmlobj xml] 235 close $fid 236 237 # Return a list of the UQ variables and their PDFs. 238 # Also turns $tfile into a template file. 239 set uq_varlist [lindex [$_xmlobj uq_get_vars $tfile] 0] 240 } 241 242 243 # execute the tool using the path from the tool description 244 if {$status == 0} { 245 set cmd [$_xmlobj get tool.command] 246 regsub -all @tool $cmd $_installdir cmd 247 set cmd [string trimleft $cmd " "] 248 249 if { $cmd == "" } { 250 puts stderr "cmd is empty" 251 return [list 1 "Command is empty.\n\nThere is no command specified by\n\n <command>\n </command>\n\nin the tool.xml file."] 252 } 253 254 if {$uq_type == ""} { 255 regsub -all @driver $cmd $file cmd 256 257 switch -glob -- [resources -jobprotocol] { 258 "submit*" { 259 # if job_protocol is "submit", then use use submit command 260 set cmd "submit --local $cmd" 261 } 262 "mx" { 263 # metachory submission 264 set cmd "mx $cmd" 265 } 266 "exec" { 267 # default -- nothing special 268 } 518 set fileName [file join $rapptureInfo(cwd) "driver[pid].xml"] 519 if { [catch { 520 set f [open $fileName w] 521 puts $f "<?xml version=\"1.0\"?>" 522 puts $f [$_xmlobj xml] 523 close $f 524 } errs] != 0 } { 525 error "can't create driver file \"$fileName\": $errs" 526 } 527 return $fileName 528 } 529 530 itcl::body Rappture::Task::GetCommand { } { 531 set cmd [$_xmlobj get tool.command] 532 regsub -all @tool $cmd $_installdir cmd 533 set cmd [string trimleft $cmd " "] 534 return $cmd 535 } 536 537 itcl::body Rappture::Task::GetSimulationCommand { driverFile } { 538 set cmd [GetCommand] 539 if { $cmd == "" } { 540 return "" 541 } 542 regsub -all @driver $cmd $driverFile cmd 543 544 switch -glob -- [resources -jobprotocol] { 545 "submit*" { 546 # if job_protocol is "submit", then use use submit command 547 set cmd "submit --local $cmd" 548 } 549 "mx" { 550 # metachory submission 551 set cmd "mx $cmd" 552 } 553 "exec" { 554 # default -- nothing special 555 } 556 } 557 return $cmd 558 } 559 560 itcl::body Rappture::Task::GetUQSimulationCommand { driverFile } { 561 set cmd [GetCommand] 562 if { $cmd == "" } { 563 return "" 564 } 565 set paramsFile [GetParamsForUQ] 566 set cmd [BuildSubmitCommand $cmd $_uq(tfile) $paramsFile] 567 file delete -force puq 568 return $cmd 569 } 570 571 itcl::body Rappture::Task::GetUQTemplateFile {} { 572 global rapptureInfo 573 # Copy xml into a new file 574 set templateFile "template[pid].xml" 575 set f [open $templateFile w] 576 puts $f "<?xml version=\"1.0\"?>" 577 puts $f [$_xmlobj xml] 578 close $f 579 580 # Return a list of the UQ variables and their PDFs. 581 # Also turns $uq(tfile) into a template file. 582 set _uq(varlist) [lindex [$_xmlobj uq_get_vars $templateFile] 0] 583 set _uq(tfile) $templateFile 584 return $templateFile 585 } 586 587 itcl::body Rappture::Task::ExecuteSimulationCommand { cmd } { 588 589 set _job(runfile) "" 590 set _job(success) 0 591 set _job(exitcode) 0 592 593 # Step 1. Write the command into the run file. 594 $_xmlobj put tool.execute $cmd 595 596 Log run started 597 Rappture::rusage mark 598 599 # Step 2. Check if it is a special case "ECHO" command which always 600 # succeeds. 601 if { [string compare -nocase -length 5 $cmd "ECHO "] == 0 } { 602 set _job(stdout) [string range $cmd 5 end] 603 set _job(success) 1 604 set _job(exitcode) 0 605 set _job(mesg) "" 606 return 1; # Success 607 } 608 609 # Step 3. Execute the command, collecting its stdout and stderr. 610 catch { 611 eval blt::bgexec [list [itcl::scope _job(control)]] \ 612 -keepnewline yes \ 613 -killsignal SIGTERM \ 614 -onoutput [list [itcl::code $this OnOutput]] \ 615 -output [list [itcl::scope _job(stdout)]] \ 616 -error [list [itcl::scope _job(stderr)]] \ 617 $cmd 618 } result 619 620 # Step 4. Check the token and the exit code. 621 set logmesg $result 622 foreach { token _job(pid) _job(exitcode) mesg } $_job(control) break 623 if { $token == "EXITED" } { 624 if { $_job(exitcode) != 0 } { 625 # This means that the program exited normally but returned a 626 # non-zero exitcode. Consider this an invalid result from the 627 # program. Append the stderr from the program to the message. 628 if {$_job(exitcode) > 128} { 629 set logmesg "Program signaled: signal was [GetSignal $_job(exitcode)]" 630 } else { 631 set logmesg "Program finished: non-zero exit code is $_job(exitcode)" 269 632 } 270 } else { 271 set params_file [_get_params $uq_varlist $uq_type $uq_args] 272 set cmd [_build_submit_cmd $cmd $tfile $params_file] 273 file delete -force puq 274 } 275 276 $_xmlobj put tool.execute $cmd 277 278 # starting job... 279 set _lastrun "" 280 _log run started 281 Rappture::rusage mark 282 283 if {0 == [string compare -nocase -length 5 $cmd "ECHO "] } { 284 set status 0; 285 set job(output) [string range $cmd 5 end] 286 } else { 287 set status [catch { 288 set ::Rappture::Task::job(control) "" 289 eval blt::bgexec \ 290 ::Rappture::Task::job(control) \ 291 -keepnewline yes \ 292 -killsignal SIGTERM \ 293 -onoutput [list [itcl::code $this _output]] \ 294 -output ::Rappture::Task::job(output) \ 295 -error ::Rappture::Task::job(error) \ 296 $cmd 297 } result] 298 299 if { $status != 0 } { 300 # We're here because the exec-ed program failed 301 set logmesg $result 302 if { $::Rappture::Task::job(control) ne "" } { 303 foreach { token pid code mesg } \ 304 $::Rappture::Task::job(control) break 305 if { $token == "EXITED" } { 306 # This means that the program exited normally but 307 # returned a non-zero exitcode. Consider this an 308 # invalid result from the program. Append the stderr 309 # from the program to the message. 310 if {$code > 128} { 311 set logmesg "Program signaled: signal was [GetSignal $code]" 312 } else { 313 set logmesg "Program finished: exit code is $code" 314 } 315 set result "$logmesg\n\n$::Rappture::Task::job(error)" 316 } elseif { $token == "abort" } { 317 # The user pressed the abort button. 318 set logmesg "Program terminated by user." 319 set result "$logmesg\n\n$::Rappture::Task::job(output)" 320 } else { 321 # Abnormal termination 322 set logmesg "Abnormal program termination: $mesg" 323 set result "$logmesg\n\n$::Rappture::Task::job(output)" 324 } 325 } 326 _log run failed [list $logmesg] 327 return [list $status $result] 328 } 329 } 330 # ...job is finished 331 array set times [Rappture::rusage measure] 332 333 if {[resources -jobprotocol] ne "submit"} { 334 set id [$_xmlobj get tool.id] 335 set vers [$_xmlobj get tool.version.application.revision] 336 set simulation simulation 337 if { $id ne "" && $vers ne "" } { 338 set pid [pid] 339 set simulation ${pid}_${id}_r${vers} 340 } 341 342 # need to save job info? then invoke the callback 343 if {[string length $jobstats] > 0} { 344 uplevel #0 $jobstats [list job [incr jobnum] \ 345 event $simulation start $times(start) \ 346 walltime $times(walltime) cputime $times(cputime) \ 347 status $status] 348 } 349 350 # 351 # Scan through stderr channel and look for statements that 352 # represent grid jobs that were executed. The statements 353 # look like this: 354 # 355 # MiddlewareTime: job=1 event=simulation start=3.001094 ... 356 # 357 set subjobs 0 358 while {[regexp -indices {(^|\n)MiddlewareTime:( +[a-z]+=[^ \n]+)+(\n|$)} $job(error) match]} { 359 foreach {p0 p1} $match break 360 if {[string index $job(error) $p0] == "\n"} { incr p0 } 361 362 catch {unset data} 363 array set data { 364 job 1 365 event simulation 366 start 0 367 walltime 0 368 cputime 0 369 status 0 370 } 371 foreach arg [lrange [string range $job(error) $p0 $p1] 1 end] { 372 foreach {key val} [split $arg =] break 373 set data($key) $val 374 } 375 set data(job) [expr {$jobnum+$data(job)}] 376 set data(event) "subsimulation" 377 set data(start) [expr {$times(start)+$data(start)}] 378 379 set details "" 380 foreach key {job event start walltime cputime status} { 381 # add required keys in a particular order 382 lappend details $key $data($key) 383 unset data($key) 384 } 385 foreach key [array names data] { 386 # add anything else that the client gave -- venue, etc. 387 lappend details $key $data($key) 388 } 389 390 if {[string length $jobstats] > 0} { 391 uplevel #0 $jobstats $details 392 } 393 394 incr subjobs 395 396 # done -- remove this statement 397 set job(error) [string replace $job(error) $p0 $p1] 398 } 399 incr jobnum $subjobs 400 } 401 633 set _job(mesg) "$logmesg\n\n$_job(stderr)" 634 Log run failed [list $logmesg] 635 return 0; # Fail. 636 } 637 # Successful program termination with exit code of 0. 638 } elseif { $token == "abort" } { 639 # The user pressed the abort button. 640 641 set logmesg "Program terminated by user." 642 Log run failed [list $logmesg] 643 set _job(mesg) "$logmesg\n\n$_job(stdout)" 644 return 0; # Fail 402 645 } else { 403 set job(error) "$result\n$errorInfo" 404 } 405 if {$status == 0} { 406 # file delete -force -- $file 407 } 408 409 # see if the job was aborted 410 if {[regexp {^KILLED} $job(control)]} { 411 _log run aborted 412 return [list 0 "ABORT"] 413 } 414 646 # Abnormal termination 647 648 set logmesg "Abnormal program termination:" 649 Log run failed [list $logmesg] 650 set _job(mesg) "$logmesg\n\n$_job(stdout)" 651 return 0; # Fail 652 } 653 if { $_uq(type) != "" } { 654 CollectUQResults 655 } 656 657 # Step 5. Look in stdout for the name of the run file. 658 set pattern {=RAPPTURE-RUN=>([^\n]+)} 659 if {![regexp $pattern $_job(stdout) match fileName]} { 660 set _job(mesg) "Can't find result file in output.\n" 661 append _job(mesg) "Did you call Rappture::result in your simulator?" 662 return 0; # Fail 663 } 664 set _job(runfile) $fileName 665 set _job(success) 1 666 set _job(mesg) $_job(stdout) 667 return 1; # Success 668 } 669 670 itcl::body Rappture::Task::LogSimulationUsage {} { 671 array set times [Rappture::rusage measure] 672 673 set toolId [$_xmlobj get tool.id] 674 set toolVers [$_xmlobj get tool.version.application.revision] 675 set simulation "simulation" 676 if { $toolId ne "" && $toolVers ne "" } { 677 set simulation "[pid]_${toolId}_r${toolVers}" 678 } 679 680 # Need to save job info? then invoke the callback 681 if { [string length $jobstats] > 0} { 682 lappend args \ 683 "job" [incr jobnum] \ 684 "event" $simulation \ 685 "start" $times(start) \ 686 "walltime" $times(walltime) \ 687 "cputime" $times(cputime) \ 688 "status" $_job(exitcode) 689 uplevel #0 $jobstats $args 690 } 691 415 692 # 416 # If successful, return the output, which should include 417 # a reference to the run.xml file containing results. 693 # Scan through stderr channel and look for statements that 694 # represent grid jobs that were executed. The statements look 695 # like this: 418 696 # 419 420 if {$status == 0} { 421 set result [string trim $job(output)] 422 423 if {$uq_type != ""} { 424 # UQ. Collect data from all jobs and put it in one xml run file. 425 file delete -force -- run_uq.xml 426 if {[catch {exec puq.sh analyze puq_[pid].hdf5} res]} { 427 set fp [open "uq_debug.err" r] 428 set rdata [read $fp] 429 close $fp 430 puts "PUQ analysis failed: $res\n$rdata" 431 error "UQ analysis failed: $res\n$rdata" 432 } else { 433 append result "\n" $res 434 } 435 } 436 if {[regexp {=RAPPTURE-RUN=>([^\n]+)} $result match file]} { 437 set _lastrun $file 438 439 set status [catch {Rappture::library $file} result] 440 if {$status == 0} { 441 # add cputime info to run.xml file 442 $result put output.walltime $times(walltime) 443 $result put output.cputime $times(cputime) 444 if {[info exists env(SESSION)]} { 445 $result put output.session $env(SESSION) 446 } 447 } else { 448 global errorInfo 449 set result "$result\n$errorInfo" 450 } 451 452 file delete -force -- $file 453 } else { 454 set status 1 455 set result "Can't find result file in output.\nDid you call Rappture 456 ::result in your simulator?" 457 } 458 } elseif {$job(output) ne "" || $job(error) ne ""} { 459 set result [string trim "$job(output)\n$job(error)"] 460 } 461 462 # log final status for the run 463 if {$status == 0} { 464 _log run finished 697 # MiddlewareTime: job=1 event=simulation start=3.001094 ... 698 # 699 700 set subjobs 0 701 set pattern {(^|\n)MiddlewareTime:( +[a-z]+=[^ \n]+)+(\n|$)} 702 while { [regexp -indices $pattern $_job(stderr) match] } { 703 foreach {p0 p1} $match break 704 if { [string index $_job(stderr) $p0] == "\n" } { 705 incr p0 706 } 707 array unset data 708 array set data { 709 job 1 710 event simulation 711 start 0 712 walltime 0 713 cputime 0 714 status 0 715 } 716 foreach arg [lrange [string range $_job(stderr) $p0 $p1] 1 end] { 717 foreach {key val} [split $arg =] break 718 set data($key) $val 719 } 720 set data(job) [expr { $jobnum + $data(job) }] 721 set data(event) "subsimulation" 722 set data(start) [expr { $times(start) + $data(start) }] 723 724 set details "" 725 foreach key {job event start walltime cputime status} { 726 # Add required keys in a particular order 727 lappend details $key $data($key) 728 unset data($key) 729 } 730 foreach key [array names data] { 731 # Add anything else that the client gave -- venue, etc. 732 lappend details $key $data($key) 733 } 734 735 if {[string length $jobstats] > 0} { 736 uplevel #0 $jobstats $details 737 } 738 739 incr subjobs 740 741 # Done -- remove this statement 742 set _job(stderr) [string replace $_job(stderr) $p0 $p1] 743 } 744 incr jobnum $subjobs 745 746 # Add cputime info to run.xml file 747 if { [catch { 748 Rappture::library $_job(runfile) 749 } xmlobj] != 0 } { 750 error "Can't create rappture library: $xmlobj" 751 } 752 $xmlobj put output.walltime $times(walltime) 753 $xmlobj put output.cputime $times(cputime) 754 global env 755 if {[info exists env(SESSION)]} { 756 $xmlobj put output.session $env(SESSION) 757 } 758 set _job(xmlobj) $xmlobj 759 } 760 761 itcl::body Rappture::Task::LogSubmittedSimulationUsage {} { 762 array set times [Rappture::rusage measure] 763 764 set toolId [$_xmlobj get tool.id] 765 set toolVers [$_xmlobj get tool.version.application.revision] 766 set simulation "simulation" 767 if { $toolId ne "" && $toolVers ne "" } { 768 set simulation "[pid]_${toolId}_r${toolVers}" 769 } 770 771 # Need to save job info? then invoke the callback 772 if { [string length $jobstats] > 0} { 773 lappend args \ 774 "job" [incr jobnum] \ 775 "event" $simulation \ 776 "start" $times(start) \ 777 "walltime" $times(walltime) \ 778 "cputime" $times(cputime) \ 779 "status" $_job(exitcode) 780 uplevel #0 $jobstats $args 781 } 782 783 # 784 # Scan through stderr channel and look for statements that 785 # represent grid jobs that were executed. The statements look 786 # like this: 787 # 788 # MiddlewareTime: job=1 event=simulation start=3.001094 ... 789 # 790 791 set subjobs 0 792 set pattern {(^|\n)MiddlewareTime:( +[a-z]+=[^ \n]+)+(\n|$)} 793 while { [regexp -indices $pattern $_job(stderr) match] } { 794 foreach {p0 p1} $match break 795 if { [string index $_job(stderr) $p0] == "\n" } { 796 incr p0 797 } 798 array unset data 799 array set data { 800 job 1 801 event simulation 802 start 0 803 walltime 0 804 cputime 0 805 status 0 806 } 807 foreach arg [lrange [string range $_job(stderr) $p0 $p1] 1 end] { 808 foreach {key val} [split $arg =] break 809 set data($key) $val 810 } 811 set data(job) [expr { $jobnum + $data(job) }] 812 set data(event) "subsimulation" 813 set data(start) [expr { $times(start) + $data(start) }] 814 815 set details "" 816 foreach key {job event start walltime cputime status} { 817 # Add required keys in a particular order 818 lappend details $key $data($key) 819 unset data($key) 820 } 821 foreach key [array names data] { 822 # Add anything else that the client gave -- venue, etc. 823 lappend details $key $data($key) 824 } 825 826 if {[string length $jobstats] > 0} { 827 uplevel #0 $jobstats $details 828 } 829 830 incr subjobs 831 832 # Done -- remove this statement 833 set _job(stderr) [string replace $_job(stderr) $p0 $p1] 834 } 835 incr jobnum $subjobs 836 837 # Add cputime info to run.xml file 838 if { [catch { 839 Rappture::library $_job(runfile) 840 } xmlobj] != 0 } { 841 error "Can't create rappture library: $xmlobj" 842 } 843 set _job(xmlobj) $xmlobj 844 } 845 846 itcl::body Rappture::Task::LogCachedSimulationUsage {} { 847 if { [catch { 848 Rappture::library $_job(runfile) 849 } xmlobj] != 0 } { 850 error "Can't create rappture library: $xmlobj" 851 } 852 # Get the session from runfile 853 set session [$xmlobj get "output.session"] 854 if { [catch {exec submit --cache $session} result] != 0 } { 855 puts stderr "submit --cache failed: $result" 856 } 857 set _job(xmlobj) $xmlobj 858 } 859 860 861 itcl::body Rappture::Task::CheckForCachedRunFile { driverFile } { 862 863 # Read the driver file and collect its contents as the query. 864 set url http://$_resources(-cachehosts)/cache/request 865 set f [open $driverFile "r"] 866 set query [read $f] 867 close $f 868 869 # Make the query 870 if { [catch { 871 http::geturl $url -query $query -timeout 6000 -binary yes 872 } token] != 0 } { 873 puts stderr "error performing cache query: token=$token" 874 return 0 875 } 876 # If the code isn't 200, we'll assume it's a cache miss. 877 if { [http::ncode $token] != 200} { 878 return 0 879 } 880 # Get contents of the run file. 881 set contents [http::data $token] 882 if { $contents == "" } { 883 return 0 884 } 885 886 # Create a new run.xml file and write the results into it. 887 set secs [clock seconds] 888 set millisecs [expr [clock clicks -milliseconds] % 1000] 889 set timestamp [format %d%03d%03d $secs $millisecs 0] 890 891 global rapptureInfo 892 set fileName [file join $rapptureInfo(cwd) "run${timestamp}.xml"] 893 set f [open $fileName "w"] 894 puts $f $contents 895 close $f 896 set _job(runfile) $fileName 897 set _job(success) 1 898 set _job(stderr) "Loading cached results\n" 899 OnOutput "Loading cached results\n" 900 update 901 return 1 902 } 903 904 itcl::body Rappture::Task::GetUQErrors {} { 905 set contents {} 906 if { [file exists "uq_debug.err"] } { 907 set f [open "uq_debug.err" r] 908 set contents [read $f] 909 close $f 910 } 911 return $contents 912 } 913 914 # UQ. Collect data from all jobs and put it in one xml run file. 915 itcl::body Rappture::Task::CollectUQResults {} { 916 file delete -force -- "run_uq.xml" 917 set hdfFile puq_[pid].hdf5 918 if { [catch { 919 exec puq.sh analyze $hdfFile 920 } results] != 0 } { 921 error "UQ analysis failed: $results\n[GetUQErrors]" 465 922 } else { 466 _log run failed [list $result] 467 } 468 469 return [list $status $result] 470 } 471 472 # ---------------------------------------------------------------------- 473 # Turn the command string from tool.xml into the proper syntax to use 474 # with a submit parameter sweep with a temlate file. Proper quoting 475 # of the template file is necessary to prevent submit from being too smart 476 # and converting it to a full pathname. 477 # ---------------------------------------------------------------------- 478 itcl::body Rappture::Task::_build_submit_cmd {cmd tfile params_file} { 479 set quote_next 0 480 set newcmd "submit --progress submit --runName=puq -l -i @:$tfile -d $params_file" 481 set cmds [split $cmd " "] 482 for {set i 0} {$i < [llength $cmds]} {incr i} { 483 set arg [lindex $cmds $i] 484 if {$quote_next == 1} { 485 set nc [string range $arg 0 0] 486 if {$nc != "\""} { 487 set arg "\"\\\"$arg\\\"\"" 488 } 489 } 490 if {$arg == "--eval"} { 491 set quote_next 1 492 } else { 493 set quote_next 0 494 } 495 if {$arg == "@driver"} { 496 set arg "\"\\\"$tfile\\\"\"" 497 } 498 append newcmd " " $arg 499 } 500 regsub -all @driver $newcmd $tfile newcmd 501 return $newcmd 502 } 503 504 # ---------------------------------------------------------------------- 505 # USAGE: _mkdir <directory> 506 # 507 # Used internally to create the <directory> in the file system. 508 # The parent directory is also created, as needed. 509 # ---------------------------------------------------------------------- 510 itcl::body Rappture::Task::_mkdir {dir} { 511 set parent [file dirname $dir] 512 if {$parent ne "." && $parent ne "/"} { 513 if {![file exists $parent]} { 514 _mkdir $parent 515 } 516 } 517 file mkdir $dir 518 } 519 520 521 # ---------------------------------------------------------------------- 522 # USAGE: abort 523 # 524 # Clients use this during a "run" to abort the current job. 525 # Kills the job and forces the "run" method to return. 526 # ---------------------------------------------------------------------- 527 itcl::body Rappture::Task::abort {} { 528 _log run abort 529 set job(control) "abort" 530 } 531 532 # ---------------------------------------------------------------------- 533 # USAGE: reset 534 # 535 # Resets all input values to their defaults. Sometimes used just 536 # before a run to reset to a clean state. 537 # ---------------------------------------------------------------------- 538 itcl::body Rappture::Task::reset {} { 539 $_xmlobj copy "" from $_origxml "" 540 foreach path [Rappture::entities -as path $_xmlobj input] { 541 if {[$_xmlobj element -as type $path.default] ne ""} { 542 set defval [$_xmlobj get $path.default] 543 $_xmlobj put $path.current $defval 544 } 545 } 546 } 547 548 # ---------------------------------------------------------------------- 549 # USAGE: xml <subcommand> ?<arg> <arg> ...? 550 # USAGE: xml object 551 # 552 # Used by clients to manipulate the underlying XML data for this 553 # tool. The <subcommand> can be any operation supported by a 554 # Rappture::library object. Clients can also request the XML object 555 # directly by using the "object" subcommand. 556 # ---------------------------------------------------------------------- 557 itcl::body Rappture::Task::xml {args} { 558 if {"object" == $args} { 559 return $_xmlobj 560 } 561 return [eval $_xmlobj $args] 562 } 563 564 # ---------------------------------------------------------------------- 565 # USAGE: save <xmlobj> ?<filename>? 566 # 567 # Used by clients to save the contents of an <xmlobj> representing 568 # a run out to the given file. If <filename> is not specified, then 569 # it uses the -resultsdir and other settings to do what Rappture 570 # would normally do with the output. 571 # ---------------------------------------------------------------------- 572 itcl::body Rappture::Task::save {xmlobj {filename ""}} { 573 if {$filename eq ""} { 574 # if there's a results_directory defined in the resources 575 # file, then move the run.xml file there for storage 576 set rdir "" 577 if {$resultdir eq "@default"} { 578 if {[info exists _resources(-resultdir)]} { 579 set rdir $_resources(-resultdir) 580 } else { 581 global rapptureInfo 582 set rdir $rapptureInfo(cwd) 583 } 584 } elseif {$resultdir ne ""} { 585 set rdir $resultdir 586 } 587 588 # use the runfile name generated by the last run 589 if {$_lastrun ne ""} { 590 set filename [file join $rdir $_lastrun] 591 } else { 592 set filename [file join $rdir run.xml] 593 } 594 } 595 596 # add any last-minute metadata 597 $xmlobj put output.time [clock format [clock seconds]] 598 599 $xmlobj put tool.version.rappture.version $::Rappture::version 600 $xmlobj put tool.version.rappture.revision $::Rappture::build 601 602 if {[info exists ::tcl_platform(user)]} { 603 $xmlobj put output.user $::tcl_platform(user) 604 } 605 606 # save the output 607 set rdir [file dirname $filename] 608 if {![file exists $rdir]} { 609 _mkdir $rdir 610 } 611 612 set fid [open $filename w] 613 puts $fid "<?xml version=\"1.0\"?>" 614 puts $fid [$xmlobj xml] 615 close $fid 616 617 _log output saved in $filename 618 } 619 620 # ---------------------------------------------------------------------- 621 # USAGE: _output <data> 622 # 623 # Used internally to send each bit of output <data> coming from the 624 # tool onto the caller, so the user can see progress. 625 # ---------------------------------------------------------------------- 626 itcl::body Rappture::Task::_output {data} { 627 if {[string length $_outputcb] > 0} { 628 uplevel #0 $_outputcb [list $data] 629 } 630 } 631 632 # ---------------------------------------------------------------------- 633 # USAGE: _log <cmd> <arg> <arg> ... 634 # 635 # Used internally to log interesting events during the run. If the 636 # -logger option is set (to Rappture::Logger::log, or something like 637 # that), then the arguments to this method are passed along to the 638 # logger and written out to a log file. Logging is off by default, 639 # so this method does nothing unless -logger is set. 640 # ---------------------------------------------------------------------- 641 itcl::body Rappture::Task::_log {args} { 642 if {[string length $logger] > 0} { 643 uplevel #0 $logger [list $args] 644 } 645 } 646 647 # ---------------------------------------------------------------------- 648 # USAGE: MiddlewareTime <key> <value> ... 649 # 650 # Used as the default method for reporting job status information. 651 # Implements the old HUBzero method of reporting job status info to 652 # stderr, which can then be picked up by the tool session container. 653 # Most tools use the "submit" command, which talks directly to a 654 # database to log job information, so this isn't really needed. But 655 # it doesn't hurt to have this and it can be useful in some cases. 656 # ---------------------------------------------------------------------- 657 itcl::body Rappture::Task::MiddlewareTime {args} { 658 set line "MiddlewareTime:" 659 foreach {key val} $args { 660 append line " $key=$val" 661 } 662 puts stderr $line 663 } 664 665 666 # 667 # Send the list of parameters to a python program so it can call PUQ 668 # and get a CSV file containing the parameter values to use for the runs. 669 itcl::body Rappture::Task::_get_params {varlist uq_type uq_args} { 670 set pid [pid] 671 # puts "puq.sh get_params $pid $varlist $uq_type $uq_args" 672 if { [catch { 673 exec puq.sh get_params $pid $varlist $uq_type $uq_args 674 } errs] != 0 } { 675 set contents {} 676 if { [file exists "uq_debug.err"] } { 677 set fp [open "uq_debug.err" r] 678 set contents [read $fp] 679 close $fp 680 } 681 puts "get_params.py failed: $errs\n$contents" 682 error "get_params.py failed: $errs\n$contents" 683 } 684 return params[pid].csv 685 } 923 set _job(stdout) $results 924 } 925 } -
trunk/src/core/RpLibrary.cc
r5673 r6473 1791 1791 1792 1792 // check for binary data 1793 // FIXME: I've already appended a NUL-byte ofthis assuming that1793 // FIXME: I've already appended a NUL-byte to this assuming that 1794 1794 // it's a ASCII string. This test must come before. 1795 1795 if (Rappture::encoding::isBinary(value.c_str(), value.length())) { … … 2047 2047 return *this; 2048 2048 } 2049 if (compress == RPLIB_COMPRESS) { 2049 if ((compress == RPLIB_COMPRESS) || 2050 (Rappture::encoding::isBinary(fileBuf.bytes(), fileBuf.size()))) { 2050 2051 putData(path, fileBuf.bytes(), fileBuf.size(), append); 2051 2052 } else {
Note: See TracChangeset
for help on using the changeset viewer.