Commit 5dfa4a47 authored by Leigh Stoller's avatar Leigh Stoller

This start out as:

* add an "active" flag to the template record, which will be used by
  the user to indicate what templates he wants listed (rather then the
  roots). Basically, the current working templates, rather then a big
  graph.

But I never actually finished that cause it sorta morphed into:

* Added a vis_graphs table to cache the last generated visualization
  rendering in the database so that we do not have to wait so long for:

* Add new buttons to showexp and template_show pages, to display in the
  same page either the settings (current view), the NS file, or the
  visualization (along with zoom in/out buttons).

And now I can go back to that "active" thing I mentioned up above ...
parent 8dd25911
......@@ -3420,6 +3420,7 @@ sub TBExptContainsNodeCT($$$)
# vis_nodes is locked during update in prerender, so we
# will get a consistent dataset when we backup.
"vis_nodes",
"vis_graphs",
"nseconfigs",
"eventlist",
"event_groups",
......
......@@ -712,6 +712,7 @@ CREATE TABLE experiment_templates (
logfile_open tinyint(4) NOT NULL default '0',
prerender_pid int(11) default '0',
hidden tinyint(1) NOT NULL default '0',
active tinyint(1) NOT NULL default '0',
PRIMARY KEY (guid,vers),
KEY pidtid (pid,tid),
KEY pideid (pid,eid)
......@@ -2904,6 +2905,19 @@ CREATE TABLE virt_vtypes (
members text
) TYPE=MyISAM;
--
-- Table structure for table `vis_graphs`
--
CREATE TABLE vis_graphs (
pid varchar(12) NOT NULL default '',
eid varchar(32) NOT NULL default '',
zoom decimal(8,3) NOT NULL default '0',
detail tinyint(2) NOT NULL default '0',
image mediumblob,
PRIMARY KEY (pid,eid)
) TYPE=MyISAM;
--
-- Table structure for table `vis_nodes`
--
......
......@@ -3534,5 +3534,27 @@ last_net_act,last_cpu_act,last_ext_act);
alter table node_types drop adminmfs_osid;
alter table node_types drop diskloadmfs_osid;
At some point you will want to drop the node_types_save table ...
At some point you will want to drop the node_types_save table
...
4.75: Add table to cache last viewed visualization, to avoid
regeneration delays.
CREATE TABLE vis_graphs (
pid varchar(12) NOT NULL default '',
eid varchar(32) NOT NULL default '',
zoom decimal(8,3) NOT NULL default '0',
detail tinyint(2) NOT NULL default '0',
image mediumblob,
PRIMARY KEY (pid,eid)
) TYPE=MyISAM;
Also add a "active" flag to the experiment_template to use in
determining which templates the user is currently interested in.
**** Skip this if you just did 4.41 above.
alter table experiment_templates add \
active tinyint(1) NOT NULL default '0';
......@@ -47,7 +47,10 @@ CREATE TABLE experiment_templates (
logfile tinytext,
logfile_open tinyint(4) NOT NULL default '0',
prerender_pid int(11) default '0',
-- Hide this template in the graph.
hidden tinyint(1) NOT NULL default '0',
-- Make this template an active template within its graph
active tinyint(1) NOT NULL default '0',
PRIMARY KEY (guid, vers),
KEY pidtid (pid,tid),
KEY pideid (pid,eid)
......
......@@ -1320,6 +1320,54 @@ sub Show($$)
return 0;
}
#
# Activate/InActivate a template. What is an active template? Its one the
# user is futzing with and wants at the top of the list. Inactive templates
# are there but not considered important.
#
sub Activate($)
{
my ($self) = @_;
# Must be a real reference.
return -1
if (! ref($self));
my $guid = $self->guid();
my $vers = $self->vers();
DBQueryWarn("update experiment_templates set active=1 ".
"where guid='$guid' and ".
" vers='$vers'")
or return -1;
Refresh($self) == 0
or return -1;
return 0;
}
sub InActivate($)
{
my ($self) = @_;
# Must be a real reference.
return -1
if (! ref($self));
my $guid = $self->guid();
my $vers = $self->vers();
DBQueryWarn("update experiment_templates set active=0 ".
"where guid='$guid' and ".
" vers='$vers'")
or return -1;
Refresh($self) == 0
or return -1;
return 0;
}
# Improve this at some point.
sub Recurse($$)
{
......@@ -1350,6 +1398,10 @@ sub Recurse($$)
push(@{ $children{$parent_vers} }, $vers);
}
# A leaf node ...
return 0
if (!exists($children{$template_vers}));
# Recurse through all the children of this template.
my @kids = @{ $children{$template_vers} };
......
......@@ -55,6 +55,8 @@ sub HideTemplate();
sub ShowTemplate();
sub ShowHidden();
sub HideHidden();
sub Activate();
sub InActivate();
#
# Testbed Support libraries
......@@ -121,6 +123,12 @@ elsif ($action eq "showhidden") {
elsif ($action eq "hidehidden") {
exit(HideHidden());
}
elsif ($action eq "activate") {
exit(Activate());
}
elsif ($action eq "inactivate") {
exit(InActivate());
}
usage();
sub HideTemplate()
......@@ -184,6 +192,21 @@ sub HideHidden()
return 0;
}
sub Activate()
{
$template->Activate() == 0
or return -1;
return 0;
}
sub InActivate()
{
$template->InActivate() == 0
or return -1;
return 0;
}
#
# Parse command arguments. Once we return from getopts, all that are
# left are the required arguments.
......
......@@ -2,7 +2,7 @@
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2003 University of Utah and the Flux Group.
# Copyright (c) 2000-2003, 2006 University of Utah and the Flux Group.
# All rights reserved.
#
......@@ -33,7 +33,6 @@ use libdb;
use libtestbed;
my $render = "$TB/libexec/vis/render";
# my $tbdata = "tbdata";
my $output;
my $zoom;
my $detail;
......
......@@ -2,7 +2,7 @@
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2005 University of Utah and the Flux Group.
# Copyright (c) 2000-2006 University of Utah and the Flux Group.
# All rights reserved.
#
......@@ -581,6 +581,13 @@ if ($noNodes) {
}
}
# Stash in database if not a thumb.
if (! $thumbnail) {
DBQueryFatal("replace into vis_graphs set ".
" pid='$pid', eid='$eid', zoom='$zoom', detail='$detail', ".
" image=" . DBQuoteSpecial($im->png));
}
#write it to stdout
binmode STDOUT;
......
......@@ -16,6 +16,9 @@ $uid = GETLOGIN();
LOGGEDINORDIE($uid);
$isadmin = ISADMIN($uid);
$tag = "Experiment";
if (!isset($show)) {
$show = "details";
}
#
# Verify page arguments.
......@@ -74,6 +77,36 @@ sajax_handle_client_request();
include("showstuff.php3");
include_once("template_defs.php");
#
# Dump the visualization into its own iframe.
#
function ShowVis($pid, $eid, $zoom = 1.25, $detail = 1) {
global $bodyclosestring;
echo "<script type='text/javascript' src='js/wz_dragdrop.js'></script>";
echo "<center>";
echo "<div id=fee style='display: block; overflow: hidden; ".
"position: relative; z-index:1010; height: 380px; ".
"width: 650px; border: 2px solid black;'>\n";
echo "<div id=myvisdiv style='position:relative;'>\n";
echo "<img id=myvisimg border=0 ";
echo " onLoad=\"setTimeout('dd.recalc()', 1000);\" ";
echo " src='top2image.php3?pid=$pid&eid=$eid".
"&zoom=$zoom&detail=$detail'>\n";
echo "</div>\n";
echo "</div>\n";
#
# This has to happen ...
#
$bodyclosestring =
"<script type='text/javascript'>
SET_DHTML(\"myvisdiv\");
</script>\n";
}
#
# Need some DB info.
#
......@@ -157,22 +190,13 @@ if ($expstate) {
}
if ($state == $TB_EXPTSTATE_ACTIVE) {
WRITESUBMENUBUTTON("Visualization, NS File, Mapping",
WRITESUBMENUBUTTON("Details and Mapping",
"shownsfile.php3?pid=$exp_pid&eid=$exp_eid");
}
else {
WRITESUBMENUBUTTON("Visualization and NS File",
WRITESUBMENUBUTTON("Experiment Details",
"shownsfile.php3?pid=$exp_pid&eid=$exp_eid");
}
if (!isset($show) || $show == "details") {
WRITESUBMENUBUTTON("Show NS File",
"showexp.php3?pid=$exp_pid&eid=$exp_eid&show=nsfile");
}
else {
WRITESUBMENUBUTTON("Hide NS File",
"showexp.php3?pid=$exp_pid&eid=$exp_eid&show=details");
}
WRITESUBMENUDIVIDER();
if (!$lockdown) {
......@@ -377,16 +401,84 @@ echo "<br>
SUBMENUEND_2B();
if (!isset($show) || $show == "details") {
#
# The center area is a form that can show NS file, Details, or Vis.
# IE complicates this, although in retrospect, I could have used plain
# input buttons instead of the fancy rendering kind of buttons, which do not
# work as expected (violates the html spec) in IE.
#
echo "<script type='text/javascript' language='javascript'>
function Show(which) {
document.form1['show'].value = which;
document.form1.submit();
return false;
}
function Zoom(howmuch) {
document.form1['zoom'].value = howmuch;
document.form1.submit();
return false;
}
</script>\n";
echo "<center>\n";
echo "<form action='showexp.php3?pid=$pid&eid=$eid' name=form1 method=post>\n";
echo "<input type=hidden name=show value=$show>\n";
echo "<input type=hidden name=zoom value='none'>\n";
echo "<button name=showns type=button value=ns onclick=\"Show('ns');\"
style='float:center; width:10%;'>NS File</button>\n";
echo "<button name=showvis type=button value=vis onclick=\"Show('vis');\"
style='float:center; width:15%;'>Visualization</button>\n";
echo "<button name=showdetails type=button value=details
onclick=\"Show('details');\"
style='float:center; width:10%;'>Settings</button>\n";
echo "<br>\n";
if ($show == "details") {
SHOWEXP($exp_pid, $exp_eid);
}
else {
elseif ($show == "ns") {
echo "<center>";
echo "<iframe width=700 height=400 scrolling=auto
echo "<iframe width=650 height=380 scrolling=auto
src='spitnsdata.php3?pid=$exp_pid&eid=$exp_eid'
border=2></iframe>\n";
echo "</center>";
}
elseif ($show == "vis") {
$newzoom = 1.15;
$newdetail = 1;
# Default is whatever we have; to avoid regen of the image.
$query_result =
DBQueryFatal("select zoom,detail from vis_graphs ".
"where pid='$pid' and eid='$eid'");
if (mysql_num_rows($query_result)) {
$row = mysql_fetch_array($query_result);
$newzoom = $row['zoom'];
}
if (isset($zoom) && $zoom != "none")
$newzoom = $zoom;
# Sanity check but lets not worry about throwing an error.
if (!TBvalid_float($newzoom))
$newzoom = 1.25;
if (!TBvalid_integer($newdetail))
$newdetail = 1;
ShowVis($pid, $eid, $newzoom, $newdetail);
$zoomout = sprintf("%.2f", $newzoom / 1.25);
$zoomin = sprintf("%.2f", $newzoom * 1.25);
echo "<button name=viszoomout type=button value=$zoomout";
echo " onclick=\"Zoom('$zoomout');\">Zoom Out</button>\n";
echo "<button name=viszoomin type=button value=$zoomin";
echo " onclick=\"Zoom('$zoomin');\">Zoom In</button>\n";
}
echo "</form>\n";
echo "</center>\n";
if (TBExptFirewall($exp_pid, $exp_eid) &&
($expstate == $TB_EXPTSTATE_ACTIVE ||
......
......@@ -135,6 +135,9 @@ class Template
function IsHidden() {
return (is_null($this->template) ? -1 : $this->template['hidden']);
}
function IsActive() {
return (is_null($this->template) ? -1 : $this->template['active']);
}
function created() {
return (is_null($this->template) ? -1 : $this->template['created']);
}
......@@ -626,6 +629,14 @@ class Template
echo "<script type='text/javascript' ".
"src='js/wz_dragdrop.js'></script>";
echo "<script type='text/javascript'>
function G${guid}_loaded() {
dd.recalc();
SetActiveTemplate(\"G$guid\", \"CurrentTemplate\",
\"Tarea${vers}\");
}
</script>\n";
echo "<center>";
echo "<div id=fee style='display: block; overflow: hidden; ".
"position: relative; z-index:1010; height: 400px; ".
......@@ -639,6 +650,7 @@ class Template
echo $imap;
echo "<img id=\"G$guid\" border=0 usemap=\"#TemplateGraph\" ";
echo " onLoad=\"setTimeout('G${guid}_loaded()', 200);\" ";
echo " src='template_graph.php?guid=$guid'>\n";
echo "</div>\n";
echo "</div>\n";
......@@ -649,9 +661,10 @@ class Template
$bodyclosestring =
"<script type='text/javascript'>
SET_DHTML(\"D$guid\");
SetActiveTemplate(\"G$guid\", \"CurrentTemplate\",
\"Tarea${vers}\");
SetActiveTemplate(\"G$guid\", \"CurrentTemplate\",
\"Tarea${vers}\");
</script>\n";
}
......@@ -669,6 +682,61 @@ class Template
echo "</center>";
}
#
# Dump the visualization into its own iframe.
#
function ShowVis($zoom = 1.25, $detail = 1) {
global $bodyclosestring;
$guid = $this->guid();
$pid = $this->pid();
$eid = $this->eid();
echo "<script type='text/javascript' ".
"src='js/wz_dragdrop.js'></script>";
echo "<center>";
echo "<div id=fee style='display: block; overflow: hidden; ".
"position: relative; z-index:1010; height: 400px; ".
"width: 700px; border: 2px solid black;'>\n";
echo "<div id=\"D$guid\" style='position:relative;'>\n";
echo "<img id=\"G$guid\" border=0 ";
echo " onLoad=\"setTimeout('dd.recalc()', 1000);\" ";
echo " src='top2image.php3?pid=$pid&eid=$eid".
"&zoom=$zoom&detail=$detail'>\n";
echo "</div>\n";
echo "</div>\n";
#
# This has to happen ...
#
$bodyclosestring =
"<script type='text/javascript'>
SET_DHTML(\"D$guid\");
</script>\n";
}
#
# Grab the zoom and detail for the current viz picture, as a default.
#
function CurrentVisDetails() {
$pid = $this->pid();
$eid = $this->eid();
$query_result =
DBQueryFatal("select zoom,detail from vis_graphs ".
"where pid='$pid' and eid='$eid'");
if (!mysql_num_rows($query_result)) {
return array(1.15, 1);
}
$row = mysql_fetch_array($query_result);
$zoom = $row['zoom'];
$detail = $row['detail'];
return array($zoom, $detail);
}
#
# Grab array of input files for a template, indexed by input_idx.
#
......
......@@ -20,6 +20,9 @@ $eid = "";
$gid = "";
$template = NULL;
$exptidx = 0;
if (!isset($show)) {
$show = "vis";
}
function CheckArguments($guid, $version) {
global $TB_EXPT_READINFO;
......@@ -67,53 +70,57 @@ function CheckArguments($guid, $version) {
CheckArguments($guid, $version);
if (isset($showtemplate) || isset($hidetemplate) ||
isset($showhidden) || isset($hidehidden) ||
isset($zoomin) || isset($zoomout)) {
if ((isset($action) && $action != "" && $action != "none") ||
($show == "graph" && isset($zoom) && $zoom != "none")) {
# Need this for scripts.
TBGroupUnixInfo($pid, $gid, $unix_gid, $unix_name);
# Hide or show templates.
if (isset($showtemplate) || isset($hidetemplate) ||
isset($showhidden) || isset($hidehidden)) {
if (isset($action) && $action != "" && $action != "none") {
$optarg = ((isset($recursive) && $recursive == "Yep") ? "-r" : "");
$reqarg = "-a ";
$versarg = "$version";
if (isset($showtemplate)) {
if ($action == "showtemplate") {
$reqarg .= "show";
}
elseif (isset($hidetemplate)) {
elseif ($action == "hidetemplate") {
$reqarg .= "hide";
}
elseif (isset($showhidden)) {
elseif ($action == "showhidden") {
$reqarg .= "showhidden";
# Applies only to root template
$versarg = "1";
}
elseif (isset($hidehidden)) {
elseif ($action == "hidehidden") {
$reqarg .= "hidehidden";
# Applies only to root template
$versarg = "1";
}
$reqarg .= " $guid/";
if (isset($showtemplate) || isset($hidetemplate)) {
$reqarg .= $version;
elseif ($action == "activate") {
$reqarg .= "activate";
}
elseif ($action == "inactivate") {
$reqarg .= "inactivate";
}
else {
# Applies only to root template
$reqarg .= 1;
PAGEARGERROR("Invalid action $action");
return;
}
$reqarg .= " $guid/$versarg";
SUEXEC($uid, "$pid,$unix_gid",
"webtemplate_control $reqarg $optarg",
SUEXEC_ACTION_DIE);
}
else {
elseif (isset($zoom) && ($zoom == "out" || $zoom == "in")) {
$optarg = "";
if (isset($zoomin)) {
if ($zoom == "in") {
$optarg = "-z in";
}
elseif (isset($zoomout)) {
else {
$optarg = "-z out";
}
......@@ -121,6 +128,7 @@ if (isset($showtemplate) || isset($hidetemplate) ||
SUEXEC($uid, "$pid,$unix_gid", "webtemplate_graph $optarg $guid",
SUEXEC_ACTION_DIE);
}
$template->Refresh();
}
#
......@@ -132,15 +140,15 @@ SUBPAGESTART();
SUBMENUSTART("Template Options");
if (!isset($show) || $show == "graph") {
WRITESUBMENUBUTTON("Show NS File &nbsp &nbsp",
if ($template->IsActive()) {
WRITESUBMENUBUTTON("InActivate Template &nbsp &nbsp",
"template_show.php?guid=$guid".
"&version=$version&show=nsfile");
"&version=$version&action=inactivate");
}
else {
WRITESUBMENUBUTTON("Show Graph &nbsp &nbsp",
WRITESUBMENUBUTTON("Activate Template &nbsp &nbsp",
"template_show.php?guid=$guid".
"&version=$version&show=graph");
"&version=$version&action=activate");
}
WRITESUBMENUBUTTON("Modify Template",
......@@ -177,24 +185,60 @@ if ($template->InstanceCount()) {
SUBMENUEND_2B();
if (!isset($show) || $show == "graph") {
$template->ShowGraph();
#
# The center area is a form that can show NS file, Template Graph, or Vis.
# IE complicates this, although in retrospect, I could have used plain
# input buttons instead of the fancy rendering kind of buttons, which do not
# work as expected (violates the html spec) in IE.
#
echo "<script type='text/javascript' language='javascript' ".
" src='template_sup.js'>\n";
echo "</script>\n";
echo "<script type='text/javascript' language='javascript'>
function Show(which) {
document.form1['show'].value = which;
document.form1.submit();
return false;
}
function Zoom(howmuch) {
document.form1['zoom'].value = howmuch;
document.form1.submit();
return false;
}
function DoAction(action) {
document.form1['action'].value = action;
document.form1.submit();
return false;
}
</script>\n";
#
# Define the control buttons.
#
echo "<center>\n";
echo "<form action='template_show.php?guid=$guid&version=$version'
method=post>\n";
echo "<center>\n";
echo "<form action='template_show.php?guid=$guid&version=$version'
name=form1 method=post>\n";
echo "<input type=hidden name=show value=$show>\n";
echo "<input type=hidden name=zoom value='none'>\n";
echo "<input type=hidden name=action value='none'>\n";
echo "<button name=showns type=button value=ns onclick=\"Show('ns');\"
style='float:center; width:15%;'>NS File</button>\n";
echo "<button name=showvis type=button value=vis onclick=\"Show('vis');\"
style='float:center; width:15%;'>Visualization</button>\n";
echo "<button name=showgraph type=button value=graph onclick=\"Show('graph');\"
style='float:center; width:15%;'>Graph</button>\n";
if ($show == "graph") {
$template->ShowGraph();
if (! $template->IsRoot()) {
if ($template->IsHidden()) {
echo "<button name=showtemplate type=submit value=Show>";
echo " Show Template</button></a>&nbsp ";
echo "<button name=showtemplate type=button value=Show";
echo " onclick=\"DoAction('showtemplate');\">Show Template";
echo "</button>&nbsp";
}
else {
echo "<button name=hidetemplate type=submit value=Hide>";
echo " Hide Template</button></a>&nbsp ";
echo "<button name=hidetemplate type=button value=Hide";
echo " onclick=\"DoAction('hidetemplate');\">Hide Template";
echo "</button>&nbsp";
}
echo "<input type=checkbox name=recursive value=Yep>Recursive? &nbsp ";
echo "&nbsp &nbsp &nbsp ";
......@@ -203,23 +247,48 @@ if (!isset($show) || $show == "graph") {
# We overload the hidden bit on the root.
if ($root->IsHidden()) {
echo "<button name=showhidden type=submit value=showhidden>";
echo " Show Hidden Templates</button></a>&nbsp &nbsp &nbsp &nbsp ";
echo "<button name=showhidden type=button value=showhidden";
echo " onclick=\"DoAction('showhidden');\">Show Hidden Templates ";
echo "</button>&nbsp &nbsp &nbsp &nbsp ";
}
else {
echo "<button name=hidehidden type=submit value=hidehidden>";
echo " Hide Hidden Templates</button></a>&nbsp &nbsp &nbsp &nbsp ";
echo "<button name=hidehidden type=button value=hidehidden";
echo " onclick=\"DoAction('hidehidden');\">Hide Hidden Templates ";
echo "</button>&nbsp &nbsp &nbsp &nbsp ";
}
echo "<button name=zoomout type=submit value=zoomout>";
echo " Zoom Out</button>\n";
echo "<button name=zoomin type=submit value=zoomin>";
echo "Zoom In</button>\n";
echo "</form>\n";
echo "</center>\n";
echo "<button name=zoomout type=button value=out";
echo " onclick=\"Zoom('out');\">Zoom Out</button>\n";
echo "<button name=zoomin type=button value=in";
echo " onclick=\"Zoom('in');\">Zoom In</button>\n";
}
else {
elseif ($show == "ns") {
$template->ShowNS();
}
elseif ($show == "vis") {
# Default is whatever we have; to avoid regen of the image.
list ($newzoom, $newdetail) = $template->CurrentVisDetails();
if (isset($zoom) && $zoom != "none")
$newzoom = $zoom;
# Sanity check but lets not worry about throwing an error.
if (!TBvalid_float($newzoom))
$newzoom = 1.25;
if (!TBvalid_integer($newdetail))
$newdetail = 1;
$template->ShowVis($newzoom, $newdetail);
$zoomout = sprintf("%.2f", $newzoom / 1.25);
$zoomin = sprintf("%.2f", $newzoom * 1.25);
echo "<button name=viszoomout type=button value=$zoomout";
echo " onclick=\"Zoom('$zoomout');\">Zoom Out</button>\n";
echo "<button name=viszoomin type=button value=$zoomin";
echo " onclick=\"Zoom('$zoomin');\">Zoom In</button>\n";
}
echo "</form>\n";
echo "</center>\n";
SUBPAGEEND();
......@@ -262,9 +331,7 @@ echo "</tr>\n";
echo "</table>\n";
echo "</center>\n";
echo "<script type='text/javascript' language='javascript' ".
" src='template_sup.js'>\n";
echo "</script>\n";
print_r($HTTP_POST_VARS);
#