Changeset 4507 for branches/1.3
- Timestamp:
- Jul 16, 2014, 1:54:18 PM (10 years ago)
- Location:
- branches/1.3
- Files:
-
- 1 deleted
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/1.3/gui/scripts/vtkmeshviewer.tcl
r4474 r4507 92 92 private method PanCamera {} 93 93 private method SetObjectStyle { dataobj } 94 private method SetOpacity { dataset }95 94 private method SetOrientation { side } 96 95 private method SetPolydataOpacity {} … … 114 113 private variable _style; # Array of current component styles. 115 114 private variable _initialStyle; # Array of initial component styles. 116 private variable _axis117 115 private variable _reset 1; # Indicates that server was reset and 118 116 # needs to be reinitialized. 119 117 120 private variable _first "" ;# This is the topmost dataset.118 private variable _first ""; # This is the topmost dataset. 121 119 private variable _start 0 122 120 private variable _title "" 123 121 124 common _downloadPopup ;# download options from popup122 common _downloadPopup; # download options from popup 125 123 private common _hardcopy 126 124 private variable _width 0 … … 184 182 set _limits(zmax) 1.0 185 183 186 array set _axis [subst { 187 xgrid 0 188 ygrid 0 189 zgrid 0 190 xcutaway 0 191 ycutaway 0 192 zcutaway 0 193 xposition 0 194 yposition 0 195 zposition 0 196 xdirection -1 197 ydirection -1 198 zdirection -1 199 visible 1 200 labels 1 201 }] 202 array set _settings [subst { 203 outline 0 204 polydata-edges 0 205 polydata-lighting 1 206 polydata-opacity 100 207 polydata-visible 1 208 polydata-wireframe 0 209 }] 184 array set _settings { 185 -axesvisible 1 186 -axislabels 1 187 -outline 0 188 -polydataedges 0 189 -polydatalighting 1 190 -polydataopacity 100 191 -polydatavisible 1 192 -polydatawireframe 0 193 -xcutaway 0 194 -xdirection -1 195 -xgrid 0 196 -xposition 0 197 -ycutaway 0 198 -ydirection -1 199 -ygrid 0 200 -yposition 0 201 -zcutaway 0 202 -zdirection -1 203 -zgrid 0 204 -zposition 0 205 } 210 206 itk_component add view { 211 207 canvas $itk_component(plotarea).view \ … … 407 403 itcl::body Rappture::VtkMeshViewer::SetPolydataOpacity {} { 408 404 set _polydataOpacityPending 0 409 foreach dataset [CurrentDatasets -visible $_first] { 410 SetOpacity $dataset 411 } 412 } 413 414 itcl::body Rappture::VtkMeshViewer::EventuallySetPolydataOpacity { args } { 405 set val $_settings(-polydataopacity) 406 set sval [expr { 0.01 * double($val) }] 407 SendCmd "polydata opacity $sval" 408 } 409 410 itcl::body Rappture::VtkMeshViewer::EventuallySetPolydataOpacity { val } { 411 set _settings(-polydataopacity) $val 415 412 if { !$_polydataOpacityPending } { 416 413 set _polydataOpacityPending 1 … … 478 475 set _dlist [lreplace $_dlist $pos $pos] 479 476 array unset _obj2ovride $dataobj-* 480 array unset _settings $dataobj-*481 477 set changed 1 482 478 } … … 832 828 $_arcball resize $w $h 833 829 DoResize 834 InitSettings axis-xgrid axis-ygrid axis-zgrid axis-mode \ 835 axis-visible axis-labels 836 830 InitSettings -xgrid -ygrid -zgrid -axismode -axesvisible -axislabels 837 831 StopBufferingCommands 838 832 SendCmd "imgflush" … … 874 868 } 875 869 lappend _obj2datasets($dataobj) $tag 876 if { [info exists _obj2ovride($dataobj-raise)] } { 870 if { [info exists _obj2ovride($dataobj-raise)] && 871 $_obj2ovride($dataobj-raise) } { 877 872 SendCmd "dataset visible 1 $tag" 878 873 SetOpacity $tag … … 896 891 } 897 892 } 898 InitSettings outline893 InitSettings -outline 899 894 if { $_reset } { 900 895 # These are settings that rely on a dataset being loaded. 901 InitSettings polydata-edges polydata-lighting polydata-opacity \902 polydata-visible polydata-wireframe896 InitSettings -polydataedges -polydatalighting -polydataopacity \ 897 -polydatavisible -polydatawireframe 903 898 904 899 set q [list $_view(qw) $_view(qx) $_view(qy) $_view(qz)] … … 1152 1147 } 1153 1148 switch -- $what { 1154 "outline" { 1155 set bool $_settings(outline) 1156 foreach dataset [CurrentDatasets -visible $_first] { 1149 "-outline" { 1150 set bool $_settings($what) 1151 # Only display a outline for the currently visible sets. 1152 SendCmd "outline visible 0" 1153 foreach dataset [CurrentDatasets -visible] { 1157 1154 SendCmd "outline visible $bool $dataset" 1158 1155 } 1159 1156 } 1160 "polydata-opacity" { 1161 foreach dataset [CurrentDatasets -visible $_first] { 1162 SetOpacity $dataset 1163 } 1164 } 1165 "polydata-wireframe" { 1166 set bool $_settings(polydata-wireframe) 1167 foreach dataset [CurrentDatasets -visible $_first] { 1168 SendCmd "polydata wireframe $bool $dataset" 1169 } 1170 } 1171 "polydata-visible" { 1172 set bool $_settings(polydata-visible) 1173 foreach dataset [CurrentDatasets -visible $_first] { 1157 "-polydataopacity" { 1158 EventuallySetPolydataOpacity 1159 } 1160 "-polydatawireframe" { 1161 set bool $_settings($what) 1162 SendCmd "polydata wireframe $bool" 1163 } 1164 "-polydatavisible" { 1165 set bool $_settings($what) 1166 # Only change visibility of data sets marked "visible". 1167 foreach dataset [CurrentDatasets -visible] { 1174 1168 SendCmd "polydata visible $bool $dataset" 1175 1169 } 1176 1170 } 1177 "polydata-lighting" { 1178 set bool $_settings(polydata-lighting) 1179 foreach dataset [CurrentDatasets -visible $_first] { 1180 SendCmd "polydata lighting $bool $dataset" 1181 } 1182 } 1183 "polydata-edges" { 1184 set bool $_settings(polydata-edges) 1185 foreach dataset [CurrentDatasets -visible $_first] { 1186 SendCmd "polydata edges $bool $dataset" 1187 } 1188 } 1189 "axis-visible" { 1190 set bool $_axis(visible) 1171 "-polydatalighting" { 1172 set bool $_settings($what) 1173 SendCmd "polydata lighting $bool" 1174 } 1175 "-polydataedges" { 1176 set bool $_settings($what) 1177 SendCmd "polydata edges $bool" 1178 } 1179 "-axesvisible" { 1180 set bool $_settings($what) 1191 1181 SendCmd "axis visible all $bool" 1192 1182 } 1193 " axis-labels" {1194 set bool $_ axis(labels)1183 "-axislabels" { 1184 set bool $_settings($what) 1195 1185 SendCmd "axis labels all $bool" 1196 1186 } 1197 " axis-xgrid" {1198 set bool $_ axis(xgrid)1187 "-xgrid" { 1188 set bool $_settings($what) 1199 1189 SendCmd "axis grid x $bool" 1200 1190 } 1201 " axis-ygrid" {1202 set bool $_ axis(ygrid)1191 "-ygrid" { 1192 set bool $_settings($what) 1203 1193 SendCmd "axis grid y $bool" 1204 1194 } 1205 " axis-zgrid" {1206 set bool $_ axis(zgrid)1195 "-zgrid" { 1196 set bool $_settings($what) 1207 1197 SendCmd "axis grid z $bool" 1208 1198 } 1209 " axis-mode" {1199 "-axismode" { 1210 1200 set mode [$itk_component(axismode) value] 1211 1201 set mode [$itk_component(axismode) translate $mode] 1212 1202 SendCmd "axis flymode $mode" 1213 1203 } 1214 " axis-xcutaway" - "axis-ycutaway" - "axis-zcutaway" {1215 set axis [string range $what 5 5]1216 set bool $_ axis(${axis}cutaway)1204 "-xcutaway" - "-ycutaway" - "-zcutaway" { 1205 set axis [string range $what 1 1] 1206 set bool $_settings($what) 1217 1207 if { $bool } { 1218 set pos [expr $_ axis(${axis}position) * 0.01]1219 set dir $_ axis(${axis}direction)1208 set pos [expr $_settings(-${axis}position) * 0.01] 1209 set dir $_settings(-${axis}direction) 1220 1210 $itk_component(${axis}CutScale) configure -state normal \ 1221 1211 -troughcolor white … … 1227 1217 } 1228 1218 } 1229 "axis-xposition" - "axis-yposition" - "axis-zposition" - 1230 "axis-xdirection" - "axis-ydirection" - "axis-zdirection" { 1231 set axis [string range $what 5 5] 1232 #set dir $_axis(${axis}direction) 1233 set pos [expr $_axis(${axis}position) * 0.01] 1219 "-xposition" - "-yposition" - "-zposition" { 1220 set axis [string range $what 1 1] 1221 set pos [expr $_settings($what) * 0.01] 1234 1222 SendCmd "renderer clipplane ${axis} $pos -1" 1223 } 1224 "-xdirection" - "-ydirection" - "-zdirection" { 1225 set axis [string range $what 1 1] 1226 puts stderr "direction not implemented" 1235 1227 } 1236 1228 default { … … 1317 1309 checkbutton $inner.mesh \ 1318 1310 -text "Show Mesh" \ 1319 -variable [itcl::scope _settings( polydata-visible)] \1320 -command [itcl::code $this AdjustSetting polydata-visible] \1311 -variable [itcl::scope _settings(-polydatavisible)] \ 1312 -command [itcl::code $this AdjustSetting -polydatavisible] \ 1321 1313 -font "Arial 9" -anchor w 1322 1314 1323 1315 checkbutton $inner.outline \ 1324 1316 -text "Show Outline" \ 1325 -variable [itcl::scope _settings( outline)] \1326 -command [itcl::code $this AdjustSetting outline] \1317 -variable [itcl::scope _settings(-outline)] \ 1318 -command [itcl::code $this AdjustSetting -outline] \ 1327 1319 -font "Arial 9" -anchor w 1328 1320 1329 1321 checkbutton $inner.wireframe \ 1330 1322 -text "Show Wireframe" \ 1331 -variable [itcl::scope _settings( polydata-wireframe)] \1332 -command [itcl::code $this AdjustSetting polydata-wireframe] \1323 -variable [itcl::scope _settings(-polydatawireframe)] \ 1324 -command [itcl::code $this AdjustSetting -polydatawireframe] \ 1333 1325 -font "Arial 9" -anchor w 1334 1326 1335 1327 checkbutton $inner.lighting \ 1336 1328 -text "Enable Lighting" \ 1337 -variable [itcl::scope _settings( polydata-lighting)] \1338 -command [itcl::code $this AdjustSetting polydata-lighting] \1329 -variable [itcl::scope _settings(-polydatalighting)] \ 1330 -command [itcl::code $this AdjustSetting -polydatalighting] \ 1339 1331 -font "Arial 9" -anchor w 1340 1332 1341 1333 checkbutton $inner.edges \ 1342 1334 -text "Show Edges" \ 1343 -variable [itcl::scope _settings( polydata-edges)] \1344 -command [itcl::code $this AdjustSetting polydata-edges] \1335 -variable [itcl::scope _settings(-polydataedges)] \ 1336 -command [itcl::code $this AdjustSetting -polydataedges] \ 1345 1337 -font "Arial 9" -anchor w 1346 1338 … … 1354 1346 } 1355 1347 bind $inner.field <<Value>> \ 1356 [itcl::code $this AdjustSetting field]1348 [itcl::code $this AdjustSetting -field] 1357 1349 1358 1350 label $inner.opacity_l -text "Opacity" -font "Arial 9" -anchor w 1359 1351 ::scale $inner.opacity -from 0 -to 100 -orient horizontal \ 1360 -variable [itcl::scope _settings( polydata-opacity)] \1352 -variable [itcl::scope _settings(-polydataopacity)] \ 1361 1353 -width 10 \ 1362 1354 -showvalue off \ 1363 -command [itcl::code $this AdjustSetting polydata-opacity]1364 $inner.opacity set $_settings( polydata-opacity)1355 -command [itcl::code $this AdjustSetting -polydataopacity] 1356 $inner.opacity set $_settings(-polydataopacity) 1365 1357 1366 1358 blt::table $inner \ … … 1389 1381 checkbutton $inner.visible \ 1390 1382 -text "Show Axes" \ 1391 -variable [itcl::scope _ axis(visible)] \1392 -command [itcl::code $this AdjustSetting axis-visible] \1383 -variable [itcl::scope _settings(-axesvisible)] \ 1384 -command [itcl::code $this AdjustSetting -axesvisible] \ 1393 1385 -font "Arial 9" 1394 1386 1395 1387 checkbutton $inner.labels \ 1396 1388 -text "Show Axis Labels" \ 1397 -variable [itcl::scope _ axis(labels)] \1398 -command [itcl::code $this AdjustSetting axis-labels] \1389 -variable [itcl::scope _settings(-axislabels)] \ 1390 -command [itcl::code $this AdjustSetting -axislabels] \ 1399 1391 -font "Arial 9" 1400 1392 1401 1393 checkbutton $inner.gridx \ 1402 1394 -text "Show X Grid" \ 1403 -variable [itcl::scope _ axis(xgrid)] \1404 -command [itcl::code $this AdjustSetting axis-xgrid] \1395 -variable [itcl::scope _settings(-xgrid)] \ 1396 -command [itcl::code $this AdjustSetting -xgrid] \ 1405 1397 -font "Arial 9" 1406 1398 checkbutton $inner.gridy \ 1407 1399 -text "Show Y Grid" \ 1408 -variable [itcl::scope _ axis(ygrid)] \1409 -command [itcl::code $this AdjustSetting axis-ygrid] \1400 -variable [itcl::scope _settings(-ygrid)] \ 1401 -command [itcl::code $this AdjustSetting -ygrid] \ 1410 1402 -font "Arial 9" 1411 1403 checkbutton $inner.gridz \ 1412 1404 -text "Show Z Grid" \ 1413 -variable [itcl::scope _ axis(zgrid)] \1414 -command [itcl::code $this AdjustSetting axis-zgrid] \1405 -variable [itcl::scope _settings(-zgrid)] \ 1406 -command [itcl::code $this AdjustSetting -zgrid] \ 1415 1407 -font "Arial 9" 1416 1408 … … 1426 1418 "outer_edges" "outer" 1427 1419 $itk_component(axismode) value "static" 1428 bind $inner.mode <<Value>> [itcl::code $this AdjustSetting axis-mode]1420 bind $inner.mode <<Value>> [itcl::code $this AdjustSetting -axismode] 1429 1421 1430 1422 blt::table $inner \ … … 1504 1496 -onimage [Rappture::icon x-cutplane] \ 1505 1497 -offimage [Rappture::icon x-cutplane] \ 1506 -command [itcl::code $this AdjustSetting axis-xcutaway] \1507 -variable [itcl::scope _ axis(xcutaway)]1498 -command [itcl::code $this AdjustSetting -xcutaway] \ 1499 -variable [itcl::scope _settings(-xcutaway)] 1508 1500 } 1509 1501 Rappture::Tooltip::for $itk_component(xCutButton) \ … … 1515 1507 -borderwidth 1 -highlightthickness 0 \ 1516 1508 -command [itcl::code $this Slice move x] \ 1517 -variable [itcl::scope _ axis(xposition)]1509 -variable [itcl::scope _settings(-xposition)] 1518 1510 } { 1519 1511 usual … … 1532 1524 -offimage [Rappture::icon arrow-up] \ 1533 1525 -offvalue 1 \ 1534 -command [itcl::code $this AdjustSetting axis-xdirection] \1535 -variable [itcl::scope _ axis(xdirection)]1536 } 1537 set _ axis(xdirection) -11526 -command [itcl::code $this AdjustSetting -xdirection] \ 1527 -variable [itcl::scope _settings(-xdirection)] 1528 } 1529 set _settings(-xdirection) -1 1538 1530 Rappture::Tooltip::for $itk_component(xDirButton) \ 1539 1531 "Toggle the direction of the X-axis cutaway" … … 1544 1536 -onimage [Rappture::icon y-cutplane] \ 1545 1537 -offimage [Rappture::icon y-cutplane] \ 1546 -command [itcl::code $this AdjustSetting axis-ycutaway] \1547 -variable [itcl::scope _ axis(ycutaway)]1538 -command [itcl::code $this AdjustSetting -ycutaway] \ 1539 -variable [itcl::scope _settings(-ycutaway)] 1548 1540 } 1549 1541 Rappture::Tooltip::for $itk_component(yCutButton) \ … … 1555 1547 -borderwidth 1 -highlightthickness 0 \ 1556 1548 -command [itcl::code $this Slice move y] \ 1557 -variable [itcl::scope _ axis(yposition)]1549 -variable [itcl::scope _settings(-yposition)] 1558 1550 } { 1559 1551 usual … … 1572 1564 -offimage [Rappture::icon arrow-up] \ 1573 1565 -offvalue 1 \ 1574 -command [itcl::code $this AdjustSetting axis-ydirection] \1575 -variable [itcl::scope _ axis(ydirection)]1566 -command [itcl::code $this AdjustSetting -ydirection] \ 1567 -variable [itcl::scope _settings(-ydirection)] 1576 1568 } 1577 1569 Rappture::Tooltip::for $itk_component(yDirButton) \ 1578 1570 "Toggle the direction of the Y-axis cutaway" 1579 set _ axis(ydirection) -11571 set _settings(-ydirection) -1 1580 1572 1581 1573 # Z-value slicer... … … 1584 1576 -onimage [Rappture::icon z-cutplane] \ 1585 1577 -offimage [Rappture::icon z-cutplane] \ 1586 -command [itcl::code $this AdjustSetting axis-zcutaway] \1587 -variable [itcl::scope _ axis(zcutaway)]1578 -command [itcl::code $this AdjustSetting -zcutaway] \ 1579 -variable [itcl::scope _settings(-zcutaway)] 1588 1580 } 1589 1581 Rappture::Tooltip::for $itk_component(zCutButton) \ … … 1595 1587 -borderwidth 1 -highlightthickness 0 \ 1596 1588 -command [itcl::code $this Slice move z] \ 1597 -variable [itcl::scope _ axis(zposition)]1589 -variable [itcl::scope _settings(-zposition)] 1598 1590 } { 1599 1591 usual … … 1611 1603 -offimage [Rappture::icon arrow-up] \ 1612 1604 -offvalue 1 \ 1613 -command [itcl::code $this AdjustSetting axis-zdirection] \1614 -variable [itcl::scope _ axis(zdirection)]1615 } 1616 set _ axis(zdirection) -11605 -command [itcl::code $this AdjustSetting -zdirection] \ 1606 -variable [itcl::scope _settings(-zdirection)] 1607 } 1608 set _settings(-zdirection) -1 1617 1609 Rappture::Tooltip::for $itk_component(zDirButton) \ 1618 1610 "Toggle the direction of the Z-axis cutaway" … … 1736 1728 set style [$dataobj hints style] 1737 1729 if { $dataobj != $_first } { 1738 set settings(- wireframe) 11730 set settings(-polydatawireframe) 1 1739 1731 } 1740 1732 … … 1743 1735 -color white 1744 1736 -edgecolor black 1745 -edges 11746 1737 -lighting 1 1747 1738 -linewidth 1.0 1748 -opacity 1.01749 1739 -outline 0 1750 -visible 1 1751 -wireframe 0 1740 -polydataedges 1 1741 -polydataopacity 1.0 1742 -polydatavisible 1 1743 -polydatawireframe 0 1752 1744 } 1753 1745 if {$type == "cloud"} { 1754 1746 set settings(-cloudstyle) points 1755 set settings(- edges) 01747 set settings(-polydataedges) 0 1756 1748 set settings(-edgecolor) white 1757 1749 } … … 1763 1755 SendCmd "outline color [Color2RGB $settings(-color)] $tag" 1764 1756 SendCmd "outline visible $settings(-outline) $tag" 1765 set _settings( outline) $settings(-outline)1757 set _settings(-outline) $settings(-outline) 1766 1758 1767 1759 SendCmd "polydata add $tag" 1768 SendCmd "polydata visible $settings(- visible) $tag"1760 SendCmd "polydata visible $settings(-polydatavisible) $tag" 1769 1761 SendCmd "polydata cloudstyle $settings(-cloudstyle) $tag" 1770 set _settings( polydata-visible) $settings(-visible)1771 SendCmd "polydata edges $settings(- edges) $tag"1772 set _settings( polydata-edges) $settings(-edges)1762 set _settings(-polydatavisible) $settings(-polydatavisible) 1763 SendCmd "polydata edges $settings(-polydataedges) $tag" 1764 set _settings(-polydataedges) $settings(-polydataedges) 1773 1765 SendCmd "polydata color [Color2RGB $settings(-color)] $tag" 1774 #SendCmd "polydata colormode constant {} $tag" 1775 SendCmd "polydata lighting $settings(- lighting) $tag"1776 set _settings( polydata-lighting) $settings(-lighting)1766 1767 SendCmd "polydata lighting $settings(-polydatalighting) $tag" 1768 set _settings(-polydatalighting) $settings(-polydatalighting) 1777 1769 SendCmd "polydata linecolor [Color2RGB $settings(-edgecolor)] $tag" 1778 1770 SendCmd "polydata linewidth $settings(-linewidth) $tag" 1779 SendCmd "polydata opacity $settings(- opacity) $tag"1780 set _settings( polydata-opacity) [expr 100.0 * $settings(-opacity)]1781 SendCmd "polydata wireframe $settings(- wireframe) $tag"1782 set _settings( polydata-wireframe) $settings(-wireframe)1771 SendCmd "polydata opacity $settings(-polydataopacity) $tag" 1772 set _settings(-polydataopacity) [expr 100.0 * $settings(-polydataopacity)] 1773 SendCmd "polydata wireframe $settings(-polydatawireframe) $tag" 1774 set _settings(-polydatawireframe) $settings(-polydatawireframe) 1783 1775 set havePolyData 1 1784 1776 } … … 1842 1834 } 1843 1835 1844 itcl::body Rappture::VtkMeshViewer::SetOpacity { dataset } {1845 set val $_settings(polydata-opacity)1846 set sval [expr { 0.01 * double($val) }]1847 if { !$_obj2ovride($dataset-raise) } {1848 # This is wrong. Need to figure out why raise isn't set with 11849 #set sval [expr $sval * .6]1850 }1851 SendCmd "polydata opacity $sval $dataset"1852 } -
branches/1.3/packages/vizservers/nanoscale/Makefile.in
r4501 r4507 24 24 RM = rm -f 25 25 26 SERVER_OBJS = server 2.o26 SERVER_OBJS = server.o 27 27 CLIENT_OBJS = client.o clientlib.o 28 28 -
branches/1.3/packages/vizservers/nanoscale/config.h.in
r2448 r4507 10 10 #undef HAVE_ARPA_INET_H 11 11 12 /* Define to 1 if you have the `avformat_alloc_context' function. */13 #undef HAVE_AVFORMAT_ALLOC_CONTEXT14 15 /* Define to 1 if you have the <Cg/cgGL.h> header file. */16 #undef HAVE_CG_CGGL_H17 18 /* Define to 1 if you have the <ffmpeg/avcodec.h> header file. */19 #undef HAVE_FFMPEG_AVCODEC_H20 21 /* Define to 1 if you have the <ffmpeg/avformat.h> header file. */22 #undef HAVE_FFMPEG_AVFORMAT_H23 24 /* Define to 1 if you have the <ffmpeg/avutil.h> header file. */25 #undef HAVE_FFMPEG_AVUTIL_H26 27 /* Define to 1 if you have the `img_convert' function. */28 #undef HAVE_IMG_CONVERT29 30 12 /* Define to 1 if you have the <inttypes.h> header file. */ 31 13 #undef HAVE_INTTYPES_H 32 14 33 /* Define to 1 if you have the `avcodec' library (-lavcodec). */34 #undef HAVE_LIBAVCODEC35 36 /* Define to 1 if you have the <libavcodec/avcodec.h> header file. */37 #undef HAVE_LIBAVCODEC_AVCODEC_H38 39 /* Define to 1 if you have the `avformat' library (-lavformat). */40 #undef HAVE_LIBAVFORMAT41 42 /* Define to 1 if you have the <libavformat/avformat.h> header file. */43 #undef HAVE_LIBAVFORMAT_AVFORMAT_H44 45 /* Define to 1 if you have the `avutil' library (-lavutil). */46 #undef HAVE_LIBAVUTIL47 48 /* Define to 1 if you have the <libavutil/avutil.h> header file. */49 #undef HAVE_LIBAVUTIL_AVUTIL_H50 51 /* Define to 1 if you have the `highgui' library (-lhighgui). */52 #undef HAVE_LIBHIGHGUI53 54 15 /* Define to 1 if you have the <memory.h> header file. */ 55 16 #undef HAVE_MEMORY_H 17 18 /* Define to 1 if you have the `mkstemps' function. */ 19 #undef HAVE_MKSTEMPS 56 20 57 21 /* Define to 1 if you have the <netdb.h> header file. */ … … 61 25 #undef HAVE_NETINET_IN_H 62 26 63 /* Define to 1 if you have the <opencv/cv.h> header file. */ 64 #undef HAVE_OPENCV_CV_H 65 66 /* Define to 1 if you have the <opencv/highgui.h> header file. */ 67 #undef HAVE_OPENCV_HIGHGUI_H 27 /* Define to 1 if you have the <Python.h> header file. */ 28 #undef HAVE_PYTHON_H 68 29 69 30 /* Define to 1 if you have the <stdint.h> header file. */ … … 97 58 #undef HAVE_UNISTD_H 98 59 99 /* Define to 1 if you have the <vtkSmartPointer.h> header file. */100 #undef HAVE_VTKSMARTPOINTER_H101 102 60 /* Define to the address where bug reports for this package should be sent. */ 103 61 #undef PACKAGE_BUGREPORT … … 112 70 #undef PACKAGE_TARNAME 113 71 72 /* Define to the home page for this package. */ 73 #undef PACKAGE_URL 74 114 75 /* Define to the version of this package. */ 115 76 #undef PACKAGE_VERSION 116 117 /* The size of `float', as computed by sizeof. */118 #undef SIZEOF_FLOAT119 120 /* The size of `int', as computed by sizeof. */121 #undef SIZEOF_INT122 123 /* The size of `long', as computed by sizeof. */124 #undef SIZEOF_LONG125 126 /* The size of `long long', as computed by sizeof. */127 #undef SIZEOF_LONG_LONG128 129 /* The size of `void *', as computed by sizeof. */130 #undef SIZEOF_VOID_P131 77 132 78 /* Define to 1 if you have the ANSI C header files. */ -
branches/1.3/packages/vizservers/nanoscale/renderservers.tcl.in
r4485 r4507 1 # 2 # This file is read by nanoscale to determine which ports to listen 3 # to and the how to start the associated render server. 4 # 5 # Render servers 6 # 7 # Server Port Usage 8 # ====== ==== ===== 9 # nanovis 2000 production 10 # vtkvis 2010 production 11 # geovis 2015 testing 12 # vmdshow 2018 testing 13 # pymol 2019 testing 14 # pymol 2020 production 15 # 16 # The syntax is 17 # register_server <name> <port> ?<flags>? { 18 # commands... 19 # } { 20 # variables... 21 # } 22 # 23 # Registers a server by <name> at port <port>. 24 # When a connection is made to <port>, <command> is run. 25 # Environment variables will be set before executing command. 26 # 27 # Note: Don't set DISPLAY here. nanoscale itself sets the DISPLAY 28 # variable. 29 # 30 # Defaults: 31 # o Server reads from file descriptor 0. 32 # o Server writes to descriptor 1. 33 # o Server stdout and stderr are redirected to a log file. 34 # 1 35 2 36 set exec_prefix "@exec_prefix@" 3 37 set bindir "@bindir@" 4 38 set libdir "@libdir@" 5 set vtkdir "@VTK_LIB_DIR@"6 39 7 # NanoVis server -- 40 # GeoVis server (port 2015) -- 41 # Map renderer 42 # 43 register_server geovis 2015 \ 44 -output 3 -logstdout no -logstderr no \ 45 { 46 ${bindir}/geovis -o 3 47 } { 48 LD_LIBRARY_PATH ${libdir} 49 OSGEARTH_DEFAULT_FONT /usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf 50 } 51 52 # NanoVis -- 53 # Server Type Volume renderer 54 # Port 2000 55 # Threaded yes 56 # Notes: 57 # o Continue to use default options until we offically upgrade 58 # nanovis to the latest release. We are currently using a 1.2 59 # version of nanovis. 60 # o Requires change to 1.2 nanovis. Can't redirect stderr to log 61 # or X will complain about performing socket operation on non-socket 62 # descriptor. 8 63 # 9 64 register_server nanovis 2000 \ … … 15 70 } 16 71 17 # VtkVis server -- 18 # 3D drawings (scene graphs), Contour and surface graphs. 72 # VtkVis -- 73 # Server type 3D drawings (scene graphs). Contour and surface graphs. 74 # Port 2010 75 # Threaded yes 76 # Notes: 77 # o Removed ${vtkdir} from LD_LIRBRARY_PATH. Not needed with VTK 6. 78 # o Using new features in nanoscale/vtkvis to use file descriptor 3 79 # for server output. No automatic logging of stdout and stderr. 19 80 # 20 81 register_server vtkvis 2010 \ 21 - logstdout no -logstderr no \82 -output 3 -logstdout no -logstderr no \ 22 83 { 23 ${bindir}/vtkvis 84 ${bindir}/vtkvis -o 3 24 85 } { 25 LD_LIBRARY_PATH ${libdir} :${vtkdir}86 LD_LIBRARY_PATH ${libdir} 26 87 } 27 88 89 # PymolProxy -- 90 # Server type Molecular layouts using Pymol viewer. 91 # Port 2020 92 # Threaded yes 93 # Notes: 94 # o Need PYMOL_SITE_PATH for parallelpiped box.py location. 95 # o Makes no sense to log stdout and stderr of the proxy. 96 # o Renamed to just pymolproxy and removed non-threaded entry. 28 97 # 29 # Pymol server (threaded version of proxy) --30 # Molecular layouts from PDB description.31 # Need PYMOL_SITE_PATH only for parallelpiped box.py location.32 #33 98 register_server pymolproxy 2020 \ 34 99 -logstdout no -logstderr no \ -
branches/1.3/packages/vizservers/nanoscale/server.c
r2403 r4507 1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 /* ====================================================================== 3 * Copyright (c) 2004-2014 HUBzero Foundation, LLC 4 * ---------------------------------------------------------------------- 5 * See the file "license.terms" for information on usage and 6 * redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES. 7 * ====================================================================== 8 */ 9 #define _GNU_SOURCE 10 #include <sys/socket.h> 11 1 12 #include <stdio.h> 13 #include <string.h> 14 #include <errno.h> 15 #include <arpa/inet.h> 16 #include <getopt.h> 17 #include <stdarg.h> 18 #include <stdlib.h> 19 #include <sys/wait.h> 20 #include <sys/stat.h> 21 #include <sys/file.h> 22 #include <syslog.h> 2 23 #include <unistd.h> 3 #include <stdlib.h>4 #include <string.h>5 #include <signal.h>6 #include <sys/types.h>7 #include <sys/socket.h>8 #include <sys/wait.h>9 #include <sys/select.h>10 #include <sys/time.h>11 #include <arpa/inet.h>12 24 #include <fcntl.h> 13 #include <netinet/in.h> 14 #include <getopt.h> 15 #include <errno.h> 16 17 // The initial request load for a new renderer. 18 #define INITIAL_LOAD 100000000.0 19 20 // The factor that the load is divided by every second. 21 #define LOAD_DROP_OFF 2.0 22 23 // The broadcast interval (in seconds) 24 #define BROADCAST_INTERVAL 5 25 26 // The load of a remote machine must be less than this factor to 27 // justify redirection. 28 #define LOAD_REDIRECT_FACTOR 0.8 29 30 // Maxium number of services we support 31 #define MAX_SERVICES 100 32 33 float load = 0; // The present load average for this system. 34 int memory_in_use = 0; // Total memory in use by this system. 35 int children = 0; // Number of children running on this system. 36 int send_fd; // The file descriptor we broadcast through. 37 struct sockaddr_in send_addr; // The subnet address we broadcast to. 38 fd_set saved_rfds; // Descriptors we're reading from. 39 fd_set pipe_rfds; // Descriptors that are pipes to children. 40 fd_set service_rfds[MAX_SERVICES]; 41 int maxCards = 1; 42 int dispNum = -1; 43 char displayVar[200]; 44 45 struct host_info { 46 struct in_addr in_addr; 47 float load; 48 int children; 25 26 #include <tcl.h> 27 28 #include "config.h" 29 30 #define TRUE 1 31 #define FALSE 0 32 33 #ifndef SERVERSFILE 34 #define SERVERSFILE "/opt/hubzero/rappture/render/lib/renderservers.tcl" 35 #endif 36 37 #ifndef LOGDIR 38 #define LOGDIR "/tmp" 39 #endif 40 41 #define ERROR(...) SysLog(LOG_ERR, __FILE__, __LINE__, __VA_ARGS__) 42 #define TRACE(...) SysLog(LOG_DEBUG, __FILE__, __LINE__, __VA_ARGS__) 43 #define WARN(...) SysLog(LOG_WARNING, __FILE__, __LINE__, __VA_ARGS__) 44 #define INFO(...) SysLog(LOG_INFO, __FILE__, __LINE__, __VA_ARGS__) 45 46 static const char *syslogLevels[] = { 47 "emergency", /* System is unusable */ 48 "alert", /* Action must be taken immediately */ 49 "critical", /* Critical conditions */ 50 "error", /* Error conditions */ 51 "warning", /* Warning conditions */ 52 "notice", /* Normal but significant condition */ 53 "info", /* Informational */ 54 "debug", /* Debug-level messages */ 49 55 }; 50 56 51 struct child_info { 52 int memory; 53 int pipefd; 54 float requests; 55 }; 56 57 struct host_info host_array[100]; 58 struct child_info child_array[100]; 59 60 /* 61 * min()/max() macros that also do 62 * strict type-checking.. See the 63 * "unnecessary" pointer comparison. 57 /* RenderServer -- 58 * 59 * Contains information to describe/execute a render server. 64 60 */ 65 #define min(x,y) ({ \ 66 typeof(x) _x = (x); \ 67 typeof(y) _y = (y); \ 68 (void) (&_x == &_y); \ 69 _x < _y ? _x : _y; }) 70 71 #define max(x,y) ({ \ 72 typeof(x) _x = (x); \ 73 typeof(y) _y = (y); \ 74 (void) (&_x == &_y); \ 75 _x > _y ? _x : _y; }) 76 61 typedef struct { 62 const char *name; /* Name of server. */ 63 int port; /* Port to listen to. */ 64 int numCmdArgs; /* # of args in command. */ 65 int numEnvArgs; /* # of args in environment. */ 66 char *const *cmdArgs; /* Command to execute for 67 * server. */ 68 char *const *envArgs; /* Environment strings to set. */ 69 int listenerFd; /* Descriptor of the listener 70 socket. */ 71 int inputFd; /* Descriptor to dup input side of 72 * server socket. */ 73 int outputFd; /* Descriptor to dup output side of 74 * server socket. */ 75 int logStdout; /* Redirect server stdout to a 76 file. */ 77 int logStderr; /* Redirect server stderr to a 78 file. */ 79 int combineLogs; /* Combine server stdout/stderr in 80 * same file. */ 81 } RenderServer; 82 83 static Tcl_HashTable serverTable; /* Table of render servers 84 * representing services available to 85 * clients. A new instance is forked 86 * and executed each time a new 87 * request is accepted. */ 88 static int debug = FALSE; 89 static pid_t serverPid; 77 90 78 91 static void 79 close_child(int pipe_fd)92 SysLog(int priority, const char *path, int lineNum, const char* fmt, ...) 80 93 { 81 int i; 82 for(i=0; i<sizeof(child_array)/sizeof(child_array[0]); i++) { 83 if (child_array[i].pipefd == pipe_fd) { 84 children--; 85 memory_in_use -= child_array[i].memory; 86 child_array[i].memory = 0; 87 FD_CLR(child_array[i].pipefd, &saved_rfds); 88 FD_CLR(child_array[i].pipefd, &pipe_rfds); 89 close(child_array[i].pipefd); 90 child_array[i].pipefd = 0; 91 break; 92 } 93 } 94 95 printf("processes=%d, memory=%d, load=%f\n", 96 children, memory_in_use, load); 97 94 #define MSG_LEN (2047) 95 char message[MSG_LEN+1]; 96 const char *s; 97 int length; 98 va_list lst; 99 100 va_start(lst, fmt); 101 s = strrchr(path, '/'); 102 if (s == NULL) { 103 s = path; 104 } else { 105 s++; 106 } 107 length = snprintf(message, MSG_LEN, "nanoscale (%d %d) %s: %s:%d ", 108 serverPid, getpid(), syslogLevels[priority], s, lineNum); 109 length += vsnprintf(message + length, MSG_LEN - length, fmt, lst); 110 message[MSG_LEN] = '\0'; 111 if (debug) { 112 fprintf(stderr, "%s\n", message); 113 } else { 114 syslog(priority, message, length); 115 } 98 116 } 99 117 100 void note_request(int fd, float value) 101 { 102 int c; 103 for(c=0; c < sizeof(child_array)/sizeof(child_array[0]); c++) { 104 if (child_array[c].pipefd == fd) { 105 child_array[c].requests += value; 106 #ifdef DEBUGGING 107 printf("Updating requests from pipefd %d to %f\n", 108 child_array[c].pipefd, 109 child_array[c].requests); 110 #endif 111 return; 112 } 113 } 114 } 115 116 volatile int sigalarm_set; 117 118 static void 119 sigalarm_handler(int signum) 120 { 121 sigalarm_set = 1; 122 } 123 124 static void 125 help(const char *argv0) 118 static void 119 Help(const char *program) 126 120 { 127 121 fprintf(stderr, 128 "Syntax: %s [-d] -b <broadcast port> -l <listen port> -s <subnet> -c 'command'\n", 129 argv0); 122 "Syntax: %s [-d] [-f serversFile] [-x numVideoCards]\n", program); 130 123 exit(1); 131 124 } 132 125 133 static void134 clear_service_fd(int fd)126 static RenderServer * 127 NewServer(Tcl_Interp *interp, const char *name) 135 128 { 136 int n; 137 138 for(n = 0; n < MAX_SERVICES; n++) { 139 if (FD_ISSET(fd, &service_rfds[n])) 140 FD_CLR(fd, &service_rfds[n]); 141 } 129 RenderServer *serverPtr; 130 131 serverPtr = malloc(sizeof(RenderServer)); 132 memset(serverPtr, 0, sizeof(RenderServer)); 133 if (serverPtr == NULL) { 134 Tcl_AppendResult(interp, "can't allocate structure for \"", 135 name, "\": ", Tcl_PosixError(interp), (char *)NULL); 136 return NULL; 137 } 138 serverPtr->name = strdup(name); 139 serverPtr->outputFd = STDOUT_FILENO; 140 serverPtr->inputFd = STDIN_FILENO; 141 serverPtr->combineLogs = TRUE; 142 serverPtr->logStdout = TRUE; 143 serverPtr->logStderr = TRUE; 144 return serverPtr; 142 145 } 143 146 144 int 145 main(int argc, char *argv[]) 147 static int 148 ParseSwitches(Tcl_Interp *interp, RenderServer *serverPtr, int *objcPtr, 149 Tcl_Obj ***objvPtr) 146 150 { 147 char server_command[MAX_SERVICES][1000]; 148 int nservices = 0; 149 int command_argc[MAX_SERVICES]; 150 char **command_argv[MAX_SERVICES]; 151 int val; 152 int listen_fd[MAX_SERVICES]; 153 int status; 154 struct sockaddr_in listen_addr; 155 struct sockaddr_in recv_addr; 156 int listen_port[MAX_SERVICES]; 157 int recv_port = -1; 158 int debug_flag = 0; 159 int n; 160 161 listen_port[0] = -1; 162 server_command[0][0] = 0; 163 164 strcpy(displayVar, "DISPLAY=:0.0"); 165 if (putenv(displayVar) < 0) { 166 perror("putenv"); 167 } 168 while(1) { 169 int c; 170 int option_index = 0; 171 struct option long_options[] = { 172 // name, has_arg, flag, val 173 { 0,0,0,0 }, 174 }; 175 176 c = getopt_long(argc, argv, "+b:c:l:s:x:d", long_options, 177 &option_index); 178 if (c == -1) 179 break; 180 181 switch(c) { 182 case 'x': /* Number of video cards */ 183 maxCards = strtoul(optarg, 0, 0); 184 if ((maxCards < 1) || (maxCards > 10)) { 185 fprintf(stderr, "bad number of max videocards specified\n"); 186 return 1; 187 } 188 break; 189 case 'd': 190 debug_flag = 1; 191 break; 192 case 'b': 193 recv_port = strtoul(optarg, 0, 0); 194 break; 195 case 'c': 196 strncpy(server_command[nservices], optarg, sizeof(server_command[0])); 197 198 if (listen_port[nservices] == -1) { 199 fprintf(stderr,"Must specify -l port before each -c command.\n"); 200 return 1; 201 } 202 203 nservices++; 204 listen_port[nservices] = -1; 205 break; 206 case 'l': 207 listen_port[nservices] = strtoul(optarg,0,0); 208 break; 209 case 's': 210 send_addr.sin_addr.s_addr = htonl(inet_network(optarg)); 211 if (send_addr.sin_addr.s_addr == -1) { 212 fprintf(stderr,"Invalid subnet broadcast address"); 213 return 1; 214 } 215 break; 216 default: 217 fprintf(stderr,"Don't know what option '%c'.\n", c); 218 return 1; 219 } 220 } 221 if (nservices == 0 || 222 recv_port == -1 || 223 server_command[0][0]=='\0') { 224 int i; 225 for (i = 0; i < argc; i++) { 226 fprintf(stderr, "argv[%d]=(%s)\n", i, argv[i]); 227 } 228 help(argv[0]); 229 return 1; 230 } 231 232 for(n = 0; n < nservices; n++) { 233 // Parse the command arguments... 234 235 command_argc[n]=0; 236 command_argv[n] = malloc((command_argc[n]+2) * sizeof(char *)); 237 command_argv[n][command_argc[n]] = strtok(server_command[n], " \t"); 238 command_argc[n]++; 239 while( (command_argv[n][command_argc[n]] = strtok(NULL, " \t"))) { 240 command_argv[n] = realloc(command_argv[n], (command_argc[n]+2) * sizeof(char *)); 241 command_argc[n]++; 242 } 243 244 // Create a socket for listening. 245 listen_fd[n] = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 246 if (listen_fd[n] < 0) { 247 perror("socket"); 248 exit(1); 249 } 250 251 // If program is killed, drop the socket address reservation immediately. 252 val = 1; 253 status = setsockopt(listen_fd[n], SOL_SOCKET, SO_REUSEADDR, &val, 254 sizeof(val)); 255 if (status < 0) { 256 perror("setsockopt"); 257 // Not fatal. Keep on going. 258 } 259 260 // Bind this address to the socket. 261 listen_addr.sin_family = AF_INET; 262 listen_addr.sin_port = htons(listen_port[n]); 263 listen_addr.sin_addr.s_addr = htonl(INADDR_ANY); 264 status = bind(listen_fd[n], (struct sockaddr *)&listen_addr, 265 sizeof(listen_addr)); 266 if (status < 0) { 267 perror("bind"); 268 exit(1); 269 } 270 271 // Listen on the specified port. 272 status = listen(listen_fd[n],5); 273 if (status < 0) { 274 perror("listen"); 275 } 276 } 277 278 // Create a socket for broadcast. 279 send_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 280 if (send_fd < 0) { 281 perror("socket"); 282 exit(1); 283 } 284 285 // If program is killed, drop the socket address reservation immediately. 286 val = 1; 287 status = setsockopt(send_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); 288 if (status < 0) { 289 perror("setsockopt"); 290 // Not fatal. Keep on going. 291 } 292 293 // We're going to broadcast through this socket. 294 val = 1; 295 status = setsockopt(send_fd, SOL_SOCKET, SO_BROADCAST, &val, sizeof(val)); 296 if (status < 0) { 297 perror("setsockopt"); 298 // Not fatal. Keep on going. 299 } 300 301 // Bind this address to the socket. 302 recv_addr.sin_family = AF_INET; 303 recv_addr.sin_port = htons(recv_port); 304 recv_addr.sin_addr.s_addr = htonl(INADDR_ANY); 305 status = bind(send_fd, (struct sockaddr *)&recv_addr, 306 sizeof(recv_addr)); 307 if (status < 0) { 308 perror("bind"); 309 exit(1); 310 } 311 312 // Set up the address that we broadcast to. 313 send_addr.sin_family = AF_INET; 314 send_addr.sin_port = htons(recv_port); 315 316 // Set up a signal handler for the alarm interrupt. 317 // It doesn't do anything other than interrupt select() below. 318 if (signal(SIGALRM, sigalarm_handler) == SIG_ERR) { 319 perror("signal SIGALRM"); 320 } 321 322 struct itimerval itvalue = { 323 {1, 0}, {1, 0} 324 }; 325 status = setitimer(ITIMER_REAL, &itvalue, NULL); 326 if (status != 0) { 327 perror("setitimer"); 328 } 329 330 // We're ready to go. Before going into the main loop, 331 // broadcast a load announcement to other machines. 332 int maxfd = send_fd; 333 FD_ZERO(&saved_rfds); 334 FD_ZERO(&pipe_rfds); 335 336 for(n = 0; n < nservices; n++) { 337 FD_ZERO(&service_rfds[n]); 338 FD_SET(listen_fd[n], &saved_rfds); 339 if (listen_fd[n] > maxfd) 340 maxfd = listen_fd[n]; 341 } 342 343 FD_SET(send_fd, &saved_rfds); 344 345 if (!debug_flag) { 346 if ( daemon(0,0) != 0 ) { 347 perror("daemon"); 348 exit(1); 349 } 350 } 351 352 while(1) { 353 fd_set rfds = saved_rfds; 354 355 status = select(maxfd+1, &rfds, NULL, NULL, 0); 356 if (status <= 0) { 357 if (sigalarm_set) { 358 sigalarm_set = 0; 359 } 360 continue; 361 } 362 363 int accepted = 0; 364 for(n = 0; n < nservices; n++) { 365 if (FD_ISSET(listen_fd[n], &rfds)) { 366 // Accept a new connection. 367 struct sockaddr_in newaddr; 368 unsigned int addrlen = sizeof(newaddr); 369 int newfd = accept(listen_fd[n], (struct sockaddr *)&newaddr, &addrlen); 370 if (newfd < 0) { 371 perror("accept"); 372 continue; 373 } 374 375 printf("New connection from %s\n", inet_ntoa(newaddr.sin_addr)); 376 FD_SET(newfd, &saved_rfds); 377 maxfd = max(maxfd, newfd); 378 FD_SET(newfd, &service_rfds[n]); 379 accepted = 1; 380 } 381 } 382 383 if (accepted) 384 continue; 385 386 if (FD_ISSET(send_fd, &rfds)) { 387 int buffer[1000]; 388 struct sockaddr_in peer_addr; 389 unsigned int len = sizeof(peer_addr); 390 status = recvfrom(send_fd, buffer, sizeof(buffer), 0, 391 (struct sockaddr*)&peer_addr, &len); 392 if (status < 0) { 393 perror("recvfrom"); 394 continue; 395 } 396 if (status != 8) { 397 fprintf(stderr,"Bogus message from %s\n", 398 inet_ntoa(peer_addr.sin_addr)); 399 continue; 400 } 401 float peer_load = ntohl(buffer[0]); 402 int peer_procs = ntohl(buffer[1]); 403 //printf("Load for %s is %f (%d processes).\n", 404 // inet_ntoa(peer_addr.sin_addr), peer_load, peer_procs); 405 int h; 406 int free_index=-1; 407 int found = 0; 408 for(h=0; h<sizeof(host_array)/sizeof(host_array[0]); h++) { 409 if (host_array[h].in_addr.s_addr == peer_addr.sin_addr.s_addr) { 410 if (host_array[h].children != peer_procs) { 411 printf("Load for %s is %f (%d processes).\n", 412 inet_ntoa(peer_addr.sin_addr), peer_load, peer_procs); 413 } 414 host_array[h].load = peer_load; 415 host_array[h].children = peer_procs; 416 found = 1; 417 break; 418 } 419 if (host_array[h].in_addr.s_addr == 0 && free_index == -1) { 420 free_index = h; 421 } 422 } 423 if (!found) { 424 host_array[free_index].in_addr.s_addr = peer_addr.sin_addr.s_addr; 425 host_array[free_index].load = peer_load; 426 } 427 continue; 428 } 429 430 int i; 431 for(i=0; i< maxfd +1; i++) { 432 if (FD_ISSET(i,&rfds)) { 433 434 // If this is a pipe, get the load. Update. 435 if (FD_ISSET(i,&pipe_rfds)) { 436 float value; 437 status = read(i, &value, sizeof(value)); 438 if (status != 4) { 439 //fprintf(stderr,"error reading pipe, child ended?\n"); 440 close_child(i); 441 /*close(i); 442 FD_CLR(i, &saved_rfds); 443 FD_CLR(i, &pipe_rfds); */ 444 } else { 445 note_request(i,value); 446 } 447 continue; 448 } 449 450 // This must be a descriptor that we're waiting to from for 451 // the memory footprint. Get it. 452 int msg; 453 status = read(i, &msg, 4); 454 if (status != 4) { 455 fprintf(stderr,"Bad status on read (%d).", status); 456 FD_CLR(i, &saved_rfds); 457 clear_service_fd(i); 458 close(i); 459 continue; 460 } 461 462 // find the new memory increment 463 int newmemory = ntohl(msg); 464 465 memory_in_use += newmemory; 466 load += 2*INITIAL_LOAD; 467 printf("Accepted new job with memory %d\n", newmemory); 468 //printf("My load is now %f\n", load); 469 470 // accept the connection. 471 msg = 0; 472 if (write(i, &msg, 4) != 4) { 473 fprintf(stderr, "short write for hostname\n"); 474 } 475 476 int pair[2]; 477 status = pipe(pair); 478 if (status != 0) { 479 perror("pipe"); 480 } 481 482 // Make the child side of the pipe non-blocking... 483 status = fcntl(pair[1], F_SETFL, O_NONBLOCK); 484 if (status < 0) { 485 perror("fcntl"); 486 } 487 dispNum++; 488 if (dispNum >= maxCards) { 489 dispNum = 0; 490 } 491 // Fork the new process. Connect i/o to the new socket. 492 status = fork(); 493 if (status < 0) { 494 perror("fork"); 495 } else if (status == 0) { 496 497 for(n = 0; n < MAX_SERVICES; n++) { 498 if (FD_ISSET(i, &service_rfds[n])) { 499 int status = 0; 500 501 if (!debug_flag) { 502 // disassociate 503 status = daemon(0,1); 504 } 505 506 if (status == 0) { 507 int fd; 508 509 dup2(i, 0); // stdin 510 dup2(i, 1); // stdout 511 dup2(i, 2); // stderr 512 dup2(pair[1],3); 513 // read end of pipe moved, and left open to 514 // prevent SIGPIPE 515 dup2(pair[0],4); 516 517 for(fd=5; fd<FD_SETSIZE; fd++) 518 close(fd); 519 520 if (maxCards > 1) { 521 displayVar[11] = dispNum + '0'; 522 } 523 execvp(command_argv[n][0], command_argv[n]); 524 } 525 _exit(errno); 526 } 527 } 528 _exit(EINVAL); 529 530 } else { 531 int c; 532 // reap initial child which will exit immediately 533 // (grandchild continues) 534 waitpid(status, NULL, 0); 535 for(c=0; c<sizeof(child_array)/sizeof(child_array[0]); c++) { 536 if (child_array[c].pipefd == 0) { 537 child_array[c].memory = newmemory; 538 child_array[c].pipefd = pair[0]; 539 child_array[c].requests = INITIAL_LOAD; 540 status = close(pair[1]); 541 if (status != 0) { 542 perror("close pair[1]"); 543 } 544 FD_SET(pair[0], &saved_rfds); 545 FD_SET(pair[0], &pipe_rfds); 546 maxfd = max(pair[0], maxfd); 547 break; 548 } 549 } 550 551 children++; 552 } 553 554 555 FD_CLR(i, &saved_rfds); 556 clear_service_fd(i); 557 close(i); 558 break; 559 } 560 561 } // for all connected_fds 562 563 } // while(1) 564 151 int i, objc; 152 Tcl_Obj **objv; 153 154 objc = *objcPtr; 155 objv = *objvPtr; 156 for (i = 3; i < objc; i += 2) { 157 const char *string; 158 char c; 159 160 string = Tcl_GetString(objv[i]); 161 if (string[0] != '-') { 162 break; 163 } 164 c = string[1]; 165 if ((c == 'i') && (strcmp(string, "-input") == 0)) { 166 int f; 167 168 if (Tcl_GetIntFromObj(interp, objv[i+1], &f) != TCL_OK) { 169 return TCL_ERROR; 170 } 171 serverPtr->inputFd = f; 172 } else if ((c == 'o') && (strcmp(string, "-output") == 0)) { 173 int f; 174 175 if (Tcl_GetIntFromObj(interp, objv[i+1], &f) != TCL_OK) { 176 return TCL_ERROR; 177 } 178 serverPtr->outputFd = f; 179 } else if ((c == 'l') && (strcmp(string, "-logstdout") == 0)) { 180 int state; 181 182 if (Tcl_GetBooleanFromObj(interp, objv[i+1], &state) != TCL_OK) { 183 return TCL_ERROR; 184 } 185 serverPtr->logStdout = state; 186 } else if ((c == 'l') && (strcmp(string, "-logstderr") == 0)) { 187 int state; 188 189 if (Tcl_GetBooleanFromObj(interp, objv[i+1], &state) != TCL_OK) { 190 return TCL_ERROR; 191 } 192 serverPtr->logStderr = state; 193 } else if ((c == 'c') && (strcmp(string, "-combinelogs") == 0)) { 194 int state; 195 196 if (Tcl_GetBooleanFromObj(interp, objv[i+1], &state) != TCL_OK) { 197 return TCL_ERROR; 198 } 199 serverPtr->combineLogs = state; 200 } else { 201 Tcl_AppendResult(interp, "unknown switch \"", string, "\"", 202 (char *)NULL); 203 return TCL_ERROR; 204 } 205 } 206 *objcPtr = objc - (i - 3); 207 *objvPtr = objv + (i - 3); 208 return TCL_OK; 565 209 } 566 210 211 /* 212 * RegisterServerCmd -- 213 * 214 * Registers a render server to be run when a client connects 215 * on the designated port. The form of the commands is 216 * 217 * register_server <name> <port> <cmd> <environ> 218 * 219 * where 220 * 221 * name Token for the render server. 222 * port Port to listen to accept connections. 223 * cmd Command to be run to start the render server. 224 * environ Name-value pairs of representing environment 225 * variables. 226 * 227 * Note that "cmd" and "environ" are variable and backslash 228 * substituted. A listener socket automatically is established on 229 * the given port to accept client requests. 230 * 231 * Example: 232 * 233 * register_server myServer 12345 ?switches? { 234 * /path/to/myserver arg arg 235 * } { 236 * LD_LIBRARY_PATH $libdir/myServer 237 * } 238 * 239 */ 240 static int 241 RegisterServerCmd(ClientData clientData, Tcl_Interp *interp, int objc, 242 Tcl_Obj *const *objv) 243 { 244 Tcl_Obj *objPtr; 245 const char *serverName; 246 int bool, isNew; 247 int f; 248 int port; 249 int numCmdArgs, numEnvArgs; 250 char *const *cmdArgs; 251 char *const *envArgs; 252 struct sockaddr_in addr; 253 RenderServer *serverPtr; 254 Tcl_HashEntry *hPtr; 255 256 if (objc < 4) { 257 Tcl_AppendResult(interp, "wrong # args: should be \"", 258 Tcl_GetString(objv[0]), " serverName port ?flags? cmd ?environ?", 259 (char *)NULL); 260 return TCL_ERROR; 261 } 262 serverName = Tcl_GetString(objv[1]); 263 if (Tcl_GetIntFromObj(interp, objv[2], &port) != TCL_OK) { 264 return TCL_ERROR; 265 } 266 hPtr = Tcl_CreateHashEntry(&serverTable, (char *)((long)port), &isNew); 267 if (!isNew) { 268 Tcl_AppendResult(interp, "a server is already listening on port ", 269 Tcl_GetString(objv[2]), (char *)NULL); 270 return TCL_ERROR; 271 } 272 serverPtr = NewServer(interp, serverName); 273 if (serverPtr == NULL) { 274 return TCL_ERROR; 275 } 276 Tcl_SetHashValue(hPtr, serverPtr); 277 if (ParseSwitches(interp, serverPtr, &objc, (Tcl_Obj ***)&objv) != TCL_OK) { 278 goto error; 279 } 280 objPtr = Tcl_SubstObj(interp, objv[3], 281 TCL_SUBST_VARIABLES | TCL_SUBST_BACKSLASHES); 282 if (Tcl_SplitList(interp, Tcl_GetString(objPtr), &numCmdArgs, 283 (const char ***)&cmdArgs) != TCL_OK) { 284 goto error; 285 } 286 serverPtr->cmdArgs = cmdArgs; 287 serverPtr->numCmdArgs = numCmdArgs; 288 289 numEnvArgs = 0; 290 envArgs = NULL; 291 if (objc == 5) { 292 objPtr = Tcl_SubstObj(interp, objv[4], 293 TCL_SUBST_VARIABLES | TCL_SUBST_BACKSLASHES); 294 if (Tcl_SplitList(interp, Tcl_GetString(objPtr), &numEnvArgs, 295 (const char ***)&envArgs) != TCL_OK) { 296 goto error; 297 } 298 if (numEnvArgs & 0x1) { 299 Tcl_AppendResult(interp, "odd # elements in enviroment list", 300 (char *)NULL); 301 goto error; 302 } 303 } 304 serverPtr->envArgs = envArgs; 305 serverPtr->numEnvArgs = numEnvArgs; 306 307 /* Create a socket for listening. */ 308 f = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 309 if (f < 0) { 310 Tcl_AppendResult(interp, "can't create listerner socket for \"", 311 serverPtr->name, "\": ", Tcl_PosixError(interp), (char *)NULL); 312 goto error; 313 } 314 315 /* If the render server instance should be killed, drop the socket address 316 * reservation immediately, don't linger. */ 317 bool = TRUE; 318 if (setsockopt(f, SOL_SOCKET, SO_REUSEADDR, &bool, sizeof(bool)) < 0) { 319 Tcl_AppendResult(interp, "can't create set socket option for \"", 320 serverPtr->name, "\": ", Tcl_PosixError(interp), (char *)NULL); 321 goto error; 322 } 323 324 /* Bind this address to the socket. */ 325 addr.sin_family = AF_INET; 326 addr.sin_port = htons(port); 327 addr.sin_addr.s_addr = htonl(INADDR_ANY); 328 if (bind(f, (struct sockaddr *)&addr, sizeof(addr)) < 0) { 329 Tcl_AppendResult(interp, "can't bind to socket for \"", 330 serverPtr->name, "\": ", Tcl_PosixError(interp), (char *)NULL); 331 goto error; 332 } 333 /* Listen on the specified port. */ 334 if (listen(f, 5) < 0) { 335 Tcl_AppendResult(interp, "can't listen to socket for \"", 336 serverPtr->name, "\": ", Tcl_PosixError(interp), (char *)NULL); 337 return TCL_ERROR; 338 } 339 serverPtr->listenerFd = f; 340 341 return TCL_OK; 342 error: 343 free(serverPtr); 344 return TCL_ERROR; 345 } 346 347 static int 348 ParseServersFile(const char *fileName) 349 { 350 Tcl_Interp *interp; 351 352 interp = Tcl_CreateInterp(); 353 Tcl_MakeSafe(interp); 354 Tcl_CreateObjCommand(interp, "register_server", RegisterServerCmd, NULL, 355 NULL); 356 if (Tcl_EvalFile(interp, fileName) != TCL_OK) { 357 ERROR("Can't add server: %s", Tcl_GetString(Tcl_GetObjResult(interp))); 358 return FALSE; 359 } 360 Tcl_DeleteInterp(interp); 361 return TRUE; 362 } 363 364 int 365 main(int argc, char **argv) 366 { 367 #ifdef SA_NOCLDWAIT 368 struct sigaction action; 369 #endif 370 fd_set serverFds; 371 int maxFd; /* Highest file descriptor in use. */ 372 char display[200]; /* String used to manage the X 373 * DISPLAY variable for each render 374 * server instance. */ 375 int maxCards; /* Maximum number of video cards, each 376 * represented by a different X 377 * screen. */ 378 int screenNum; /* Current X screen number. */ 379 Tcl_HashEntry *hPtr; 380 Tcl_HashSearch iter; 381 const char *fileName; /* Path to servers file. */ 382 383 serverPid = getpid(); 384 screenNum = 0; 385 maxCards = 1; 386 fileName = SERVERSFILE; 387 debug = FALSE; 388 389 strcpy(display, ":0.0"); 390 Tcl_InitHashTable(&serverTable, TCL_ONE_WORD_KEYS); 391 392 /* Process command line switches. */ 393 for (;;) { 394 int c; 395 int option_index = 0; 396 struct option long_options[] = { 397 // name, has_arg, flag, val 398 { 0,0,0,0 }, 399 }; 400 401 c = getopt_long(argc, argv, "x:f:d", long_options, &option_index); 402 if (c == -1) { 403 break; 404 } 405 406 switch(c) { 407 case 'x': /* Number of video cards */ 408 maxCards = strtoul(optarg, 0, 0); 409 if ((maxCards < 1) || (maxCards > 10)) { 410 fprintf(stderr, "Bad number of max videocards specified\n"); 411 return 1; 412 } 413 break; 414 case 'd': /* Debug */ 415 debug = TRUE; 416 break; 417 418 case 'f': /* Server file path. */ 419 fileName = strdup(optarg); 420 break; 421 422 default: 423 fprintf(stderr,"Don't know what option '%c'.\n", c); 424 Help(argv[0]); 425 exit(1); 426 } 427 } 428 429 if (!debug) { 430 /* Detach this process from the controlling terminal process. The 431 * current directory becomes /tmp and redirect stdin/stdout/stderr to 432 * /dev/null. */ 433 if (daemon(0,0) < 0) { 434 ERROR("Can't daemonize nanoscale: %s", strerror(errno)); 435 exit(1); 436 } 437 } 438 serverPid = getpid(); 439 if (!ParseServersFile(fileName)) { 440 exit(1); 441 } 442 443 if (serverTable.numEntries == 0) { 444 ERROR("No servers designated."); 445 exit(1); 446 } 447 signal(SIGPIPE, SIG_IGN); 448 #ifdef SA_NOCLDWAIT 449 memset(&action, 0, sizeof(action)); 450 action.sa_flags = SA_NOCLDWAIT; 451 sigaction(SIGCHLD, &action, 0); 452 #else 453 signal(SIGCHLD, SIG_IGN); 454 #endif 455 456 /* Build the array of servers listener file descriptors. */ 457 FD_ZERO(&serverFds); 458 maxFd = -1; 459 for (hPtr = Tcl_FirstHashEntry(&serverTable, &iter); hPtr != NULL; 460 hPtr = Tcl_NextHashEntry(&iter)) { 461 RenderServer *serverPtr; 462 463 serverPtr = Tcl_GetHashValue(hPtr); 464 FD_SET(serverPtr->listenerFd, &serverFds); 465 if (serverPtr->listenerFd > maxFd) { 466 maxFd = serverPtr->listenerFd; 467 } 468 } 469 470 for (;;) { 471 fd_set readFds; 472 473 /* Reset using the array of server file descriptors. */ 474 memcpy(&readFds, &serverFds, sizeof(serverFds)); 475 if (select(maxFd+1, &readFds, NULL, NULL, 0) <= 0) { 476 ERROR("Select failed: %s", strerror(errno)); 477 break; /* Error on select. */ 478 } 479 for (hPtr = Tcl_FirstHashEntry(&serverTable, &iter); hPtr != NULL; 480 hPtr = Tcl_NextHashEntry(&iter)) { 481 RenderServer *serverPtr; 482 pid_t child; 483 int sock; 484 socklen_t length; 485 struct sockaddr_in newaddr; 486 487 serverPtr = Tcl_GetHashValue(hPtr); 488 if (!FD_ISSET(serverPtr->listenerFd, &readFds)) { 489 continue; 490 } 491 /* Rotate the display's screen number. If we have multiple video 492 * cards, try to spread the jobs out among them. */ 493 screenNum++; 494 if (screenNum >= maxCards) { 495 screenNum = 0; 496 } 497 /* Accept the new connection. */ 498 length = sizeof(newaddr); 499 #ifdef HAVE_ACCEPT4 500 sock = accept4(serverPtr->listenerFd, (struct sockaddr *)&newaddr, 501 &length, SOCK_CLOEXEC); 502 #else 503 sock = accept(serverPtr->listenerFd, (struct sockaddr *)&newaddr, 504 &length); 505 #endif 506 if (sock < 0) { 507 ERROR("Can't accept server \"%s\": %s", serverPtr->name, 508 strerror(errno)); 509 exit(1); 510 } 511 #ifndef HAVE_ACCEPT4 512 int flags = fcntl(sock, F_GETFD); 513 flags |= FD_CLOEXEC; 514 if (fcntl(sock, F_SETFD, flags) < 0) { 515 ERROR("Can't set FD_CLOEXEC on socket \"%s\": %s", 516 serverPtr->name, strerror(errno)); 517 exit(1); 518 } 519 #endif 520 INFO("Connecting \"%s\" to %s\n", serverPtr->name, 521 inet_ntoa(newaddr.sin_addr)); 522 523 /* Fork the new process. Connect I/O to the new socket. */ 524 child = fork(); 525 if (child < 0) { 526 ERROR("Can't fork \"%s\": %s", serverPtr->name, 527 strerror(errno)); 528 continue; 529 } 530 if (child == 0) { /* Child process. */ 531 int i; 532 533 if ((!debug) && (setsid() < 0)) { 534 ERROR("Can't setsid \"%s\": %s", serverPtr->name, 535 strerror(errno)); 536 exit(1); 537 } 538 if ((!debug) && ((chdir("/")) < 0)) { 539 ERROR("Can't change to root directory for \"%s\": %s", 540 serverPtr->name, strerror(errno)); 541 exit(1); 542 } 543 if (serverPtr->combineLogs) { 544 char path[BUFSIZ]; 545 int newFd; 546 547 sprintf(path, "%s/%s-%d.log", LOGDIR, 548 serverPtr->name, getpid()); 549 if (serverPtr->logStdout) { 550 newFd = open(path, O_WRONLY | O_CREAT| O_TRUNC, 0600); 551 } else { 552 newFd = open("/dev/null", O_WRONLY, 0600); 553 } 554 if (newFd < 0) { 555 ERROR("%s: can't open \"%s\": %s", serverPtr->name, 556 path, strerror(errno)); 557 exit(1); 558 } 559 if (dup2(newFd, 1) < 0) { 560 ERROR("%s: can't dup stdout to \"%s\": %s", 561 serverPtr->name, path, strerror(errno)); 562 exit(1); 563 } 564 if (dup2(newFd, 2) < 0) { 565 ERROR("%s: can't dup stderr to \"%s\": %s", 566 serverPtr->name, path, strerror(errno)); 567 exit(1); 568 } 569 } else { 570 char path[BUFSIZ]; 571 int newFd; 572 573 sprintf(path, "%s/%s-%d.stdout", LOGDIR, 574 serverPtr->name, getpid()); 575 if (serverPtr->logStdout) { 576 newFd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0600); 577 } else { 578 newFd = open("/dev/null", O_WRONLY, 0600); 579 } 580 if (newFd < 0) { 581 ERROR("%s: can't open \"%s\": %s", serverPtr->name, 582 path, strerror(errno)); 583 exit(1); 584 } 585 if (dup2(newFd, 1) < 0) { 586 ERROR("%s: can't dup stdout to \"%s\": %s", 587 serverPtr->name, path, strerror(errno)); 588 exit(1); 589 } 590 sprintf(path, "%s/%s-%d.stderr", LOGDIR, 591 serverPtr->name, getpid()); 592 if (serverPtr->logStderr) { 593 newFd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0600); 594 } else { 595 newFd = open("/dev/null", O_WRONLY, 0600); 596 } 597 if (newFd < 0) { 598 ERROR("%s: can't open \"%s\": %s", serverPtr->name, 599 path, strerror(errno)); 600 exit(1); 601 } 602 if (dup2(newFd, 2) < 0) { 603 ERROR("%s: can't dup stderr to \"%s\": %s", 604 serverPtr->name, path, strerror(errno)); 605 exit(1); 606 } 607 } 608 /* Dup the socket to descriptors, e.g. 3 and 4 */ 609 if (dup2(sock, serverPtr->inputFd) < 0) { /* input */ 610 ERROR("%s: can't dup socket to fd %d: %s", 611 serverPtr->name, serverPtr->inputFd, 612 strerror(errno)); 613 exit(1); 614 } 615 /* If using a single descriptor for input and output, we don't 616 * need to call dup2 again 617 */ 618 if (serverPtr->outputFd != serverPtr->inputFd) { 619 if (dup2(sock, serverPtr->outputFd) < 0) { /* output */ 620 ERROR("%s: can't dup socket to fd %d: %s", 621 serverPtr->name, serverPtr->outputFd, 622 strerror(errno)); 623 exit(1); 624 } 625 } 626 /* Close all the other descriptors. */ 627 for (i = 3; i <= FD_SETSIZE; i++) { 628 if (i != serverPtr->inputFd && 629 i != serverPtr->outputFd) { 630 close(i); 631 } 632 } 633 634 /* Set the screen number in the DISPLAY variable. */ 635 display[3] = screenNum + '0'; 636 setenv("DISPLAY", display, 1); 637 /* Set the enviroment, if necessary. */ 638 for (i = 0; i < serverPtr->numEnvArgs; i += 2) { 639 setenv(serverPtr->envArgs[i], serverPtr->envArgs[i+1], 1); 640 } 641 { 642 char *cmd; 643 644 cmd = Tcl_Merge(serverPtr->numCmdArgs, 645 (const char *const *)serverPtr->cmdArgs); 646 INFO("Executing %s: client=%s, \"%s\" in=%d out=%d on DISPLAY=%s", 647 serverPtr->name, inet_ntoa(newaddr.sin_addr), 648 cmd, serverPtr->inputFd, serverPtr->outputFd, display); 649 /* Replace the current process with the render server. */ 650 execvp(serverPtr->cmdArgs[0], serverPtr->cmdArgs); 651 ERROR("Can't execute \"%s\": %s", cmd, strerror(errno)); 652 Tcl_Free(cmd); 653 exit(1); 654 } 655 } else { 656 close(sock); 657 } 658 } 659 } 660 exit(1); 661 }
Note: See TracChangeset
for help on using the changeset viewer.