Index: branches/eam_branches/ipp-20100621/tools/czartool/CzarDb.pm
===================================================================
--- branches/eam_branches/ipp-20100621/tools/czartool/CzarDb.pm	(revision 28794)
+++ branches/eam_branches/ipp-20100621/tools/czartool/CzarDb.pm	(revision 28980)
@@ -16,5 +16,5 @@
 
     # Call the constructor of the parent class, Person.
-    my $self = $class->SUPER::new( $_[1], $_[2], $_[3], $_[4],  $_[5], $_[6]);
+    my $self = $class->SUPER::new($_[1], $_[2], $_[3], $_[4],  $_[5], $_[6]);
 
     bless $self, $class;
@@ -66,4 +66,39 @@
 
        $query->execute;
+}
+
+###########################################################################
+#
+# Gets revert status for this stage
+#
+###########################################################################
+sub getRevertStatus {
+    my ($self, $stage, $reverting) = @_;
+
+    my $query = $self->{_db}->prepare(<<SQL);
+    SELECT reverting 
+        FROM reverts
+         WHERE stage LIKE '$stage'; 
+SQL
+
+    $query->execute;
+    return scalar $query->fetchrow_array();
+}
+
+###########################################################################
+#
+# Updates revert status for this stage
+#
+###########################################################################
+sub updateRevertStatus {
+    my ($self, $stage, $reverting) = @_;
+
+    my $query = $self->{_db}->prepare(<<SQL);
+     UPDATE reverts 
+         SET reverting = $reverting 
+         WHERE stage LIKE '$stage';
+SQL
+
+    $query->execute;
 }
 
@@ -117,4 +152,46 @@
     }
 }
+
+###########################################################################
+#
+# Updates hosts table
+#
+###########################################################################
+sub updateHost {
+    my ($self, $host, $total, $available, $used, $readable, $writable) = @_;
+
+    my $query = $self->{_db}->prepare(<<SQL);
+    DELETE FROM hosts WHERE host LIKE '$host';
+SQL
+
+    $query->execute;
+    $query = $self->{_db}->prepare(<<SQL);
+    INSERT INTO hosts
+        (host, total, available, used, readable, writable)
+        VALUES
+        ('$host', $total, $available, $used, $readable, $writable);
+SQL
+    $query->execute;
+
+}
+
+###########################################################################
+#
+# Inserts new cluster space info
+#
+###########################################################################
+sub insertNewClusterSpace {
+    my ($self, $total, $available, $used, $hostsOver98) = @_;
+
+    my $query = $self->{_db}->prepare(<<SQL);
+    INSERT INTO cluster_space
+        (total, available, used, hostsOver98)
+        VALUES
+        ( $total, $available, $used, $hostsOver98);
+SQL
+
+        $query->execute;
+}
+
 ###########################################################################
 #
@@ -123,11 +200,11 @@
 ###########################################################################
 sub insertNewTimeData {
-    my ($self, $stage, $label, $pending, $processed, $faults, $reverting) = @_;
+    my ($self, $stage, $label, $pending, $processed, $faults) = @_;
 
     my $query = $self->{_db}->prepare(<<SQL);
     INSERT INTO $stage
-        (label, pending, processed, faults, reverting)
+        (label, pending, processed, faults)
         VALUES
-        ('$label', $pending, $processed, $faults, $reverting);
+        ('$label', $pending, $processed, $faults);
 SQL
 
@@ -158,13 +235,11 @@
 SQL
 
-
-
     if (!$query->execute) {return undef;}
 
-    my $minProcessed;
+    my $minProcessed = undef;
 
     ($minProcessed, ${$maxY}, ${$minY}, ${$maxX}, ${$minX}, ${$timeDiff}) = $query->fetchrow_array();
 
-    if (!$minProcessed) {return undef;}
+    if (!defined $minProcessed) {return undef;}
 
     $query = $self->{_db}->prepare(<<SQL);
@@ -273,4 +348,128 @@
 ###########################################################################
 #
+# Gets host data and stores it to temp file
+#
+###########################################################################
+sub createHostsData {
+    my ($self, $limit) = @_;
+
+    my $dataFile = "/tmp/czarplot_hosts_space.dat";
+    open (GNUDAT, ">$dataFile");
+
+    my $query = $self->{_db}->prepare(<<SQL);
+    SELECT 
+        host, used, available, writable, readable 
+        FROM hosts
+        ORDER BY host;
+SQL
+
+    $query->execute;
+
+    my $underLimit;
+
+    # loop round results
+    while (my @row = $query->fetchrow_array()) {
+
+        my ($host, $used, $available, $writable, $readable) = @row;
+   
+        if (($used/($used+$available))*100 > $limit) {$underLimit = 0;}
+        else {$underLimit = 1;}
+
+        # Col 1: host
+        print GNUDAT "$host";
+        
+        # Col 2: available, readable used space under limit
+        if ($readable && $underLimit) {print GNUDAT " $used";}
+        else {print GNUDAT " 0";}
+
+        # Col 3: available, readable used space OVER limit
+        if ($readable && !$underLimit) {print GNUDAT " $used";}
+        else {print GNUDAT " 0";}
+
+        # Col 4: NOT available used space
+        if (!$readable) {print GNUDAT " $used";}
+        else {print GNUDAT " 0";}
+
+        # Col 5: available writable space
+        if($writable) {print GNUDAT " $available";}
+        else {print GNUDAT " 0";}
+
+        # Col 6: NOT available writable space
+        if(!$writable) {print GNUDAT " $available";}
+        else {print GNUDAT " 0";}
+
+        print GNUDAT "\n";
+    }
+    close(GNUDAT);
+
+    return $dataFile;
+}
+
+###########################################################################
+#
+# Gets total used cluster space as a percentage
+#
+############################################################################
+sub getTotalClusterStorageAsPercentage {
+    my ($self) = @_;
+
+    my $query = $self->{_db}->prepare(<<SQL);
+    SELECT used/total*100 
+        FROM cluster_space 
+        ORDER BY timestamp DESC LIMIT 1;
+SQL
+    $query->execute;
+    return scalar $query->fetchrow_array();
+}
+
+###########################################################################
+#
+# Gets time series data for cluster storage and saves it to file 
+#
+###########################################################################
+sub createStorageTimeSeriesData {
+    my ($self, $fromTime, $toTime, $minX, $maxX, $minY, $maxY, $timeDiff) = @_;
+
+    my $dataFile = "/tmp/czarplot_gnuplot_storage_timeseries.dat";
+    open (GNUDAT, ">$dataFile");
+
+    my $query = $self->{_db}->prepare(<<SQL);
+    SELECT 
+        MAX(available), MIN(available),  
+        DATE_FORMAT(MAX(timestamp),'$self->{_dateFormat}'), 
+        DATE_FORMAT(MIN(timestamp),'$self->{_dateFormat}'),
+        TIME_TO_SEC(TIMEDIFF(max(timestamp ), min(timestamp)))
+            FROM cluster_space 
+            WHERE timestamp >= '$fromTime' AND timestamp <= '$toTime'; 
+SQL
+
+
+    if (!$query->execute) {return undef;}
+
+    (${$maxY}, ${$minY}, ${$maxX}, ${$minX}, ${$timeDiff}) = $query->fetchrow_array();
+
+
+    $query = $self->{_db}->prepare(<<SQL);
+    SELECT 
+        DATE_FORMAT(timestamp, '$self->{_dateFormat}'), available 
+        FROM cluster_space 
+        WHERE timestamp >= '$fromTime' AND timestamp <= '$toTime' 
+        ORDER BY timestamp;
+SQL
+
+    $query->execute;
+
+    # loop round results
+    while (my @row = $query->fetchrow_array()) {
+
+        my ($timestamp, $available) = @row;
+        print GNUDAT "$timestamp $available\n";
+    }
+    close(GNUDAT);
+
+    return $dataFile;
+}
+###########################################################################
+#
 # Determines how much has been processed in the provided interval of time 
 # (format: 1 HOUR, 1 MINUTE 1 DAY etc)
@@ -301,5 +500,5 @@
 
     my $currentRevision = -1;
-    my $latestRevision = 7;
+    my $latestRevision = 10;
 
     while ($currentRevision != $latestRevision) {
@@ -315,5 +514,44 @@
         elsif ($currentRevision == 5) {$self->createRevision_6();}
         elsif ($currentRevision == 6) {$self->createRevision_7();}
-    }
+        elsif ($currentRevision == 7) {$self->createRevision_8();}
+        elsif ($currentRevision == 8) {$self->createRevision_9();}
+        elsif ($currentRevision == 9) {$self->createRevision_10();}
+    }
+}
+
+#######################################################################################
+# 
+# Sets current revision of ippToPsps database
+#
+#######################################################################################
+sub setRevision {
+    my ($self, $revision) = @_;
+
+    my $query = $self->{_db}->prepare(<<SQL);
+    INSERT INTO revision (revision) VALUES ($revision);
+SQL
+    $query->execute;
+}
+
+#######################################################################################
+# 
+# Gets current revision of ippToPsps database
+#
+#######################################################################################
+sub getRevision {
+    my ($self) = @_;
+
+    if (!$self->SUPER::doesTableExist("revision")) {return 0;}
+
+    my $query = $self->{_db}->prepare(<<SQL);
+    SELECT revision
+        FROM revision
+        ORDER BY revision DESC LIMIT 1;
+SQL
+
+    $query->execute;
+    my @row = $query->fetchrow_array();
+
+    return $row[0];
 }
 
@@ -500,36 +738,105 @@
 #######################################################################################
 # 
-# Sets current revision of ippToPsps database
-#
-#######################################################################################
-sub setRevision {
-    my ($self, $revision) = @_;
-
-    my $query = $self->{_db}->prepare(<<SQL);
-    INSERT INTO revision (revision) VALUES ($revision);
-SQL
-    $query->execute;
-}
-
-#######################################################################################
-# 
-# Gets current revision of ippToPsps database
-#
-#######################################################################################
-sub getRevision {
-    my ($self) = @_;
-
-    if (!$self->SUPER::doesTableExist("revision")) {return 0;}
-
-    my $query = $self->{_db}->prepare(<<SQL);
-    SELECT revision
-        FROM revision
-        ORDER BY revision DESC LIMIT 1;
-SQL
-
-    $query->execute;
-    my @row = $query->fetchrow_array();
-
-    return $row[0];
+# Create revision 8 of the database 
+#
+#######################################################################################
+sub createRevision_8 {
+    my ($self) = @_;
+
+    print "* Creating revision 8 of '$self->{_dbName}'\n";
+
+    # drop reverting column from all stages tables
+    my $stage = undef;
+    foreach $stage (@stages) {
+
+        my $query = $self->{_db}->prepare(<<SQL);
+        ALTER TABLE $stage 
+            DROP COLUMN reverting;
+SQL
+
+    $query->execute;
+    }
+
+    # create new 'revert' table
+    my $query = $self->{_db}->prepare(<<SQL);
+    CREATE TABLE reverts (
+            stage VARCHAR(128), 
+            reverting TINYINT);
+SQL
+
+    $query->execute;
+
+    # insert stages into revert table
+    foreach $stage (@stages) {
+        my $query = $self->{_db}->prepare(<<SQL);
+        INSERT INTO reverts
+            (stage, reverting)
+            VALUES
+            ('$stage', 0);
+SQL
+       $query->execute;
+    }
+
+    $self->setRevision(8);
+}
+
+#######################################################################################
+# 
+# Create revision 9 of the database 
+#
+#######################################################################################
+sub createRevision_9 {
+    my ($self) = @_;
+
+    print "* Creating revision 9 of '$self->{_dbName}'\n";
+
+    my $query = $self->{_db}->prepare(<<SQL);
+    CREATE TABLE cluster_space (
+            timestamp TIMESTAMP DEFAULT NOW(),
+            total FLOAT, 
+            available FLOAT, 
+            used FLOAT, 
+            hostsOver98 SMALLINT);
+SQL
+
+      $query->execute;
+    $query = $self->{_db}->prepare(<<SQL);
+    CREATE TABLE hosts (
+            host VARCHAR(128), 
+            total FLOAT, 
+            available FLOAT, 
+            used FLOAT); 
+SQL
+
+      $query->execute;
+
+        $query = $self->{_db}->prepare(<<SQL);
+        CREATE INDEX clusterSpaceIndex ON cluster_space (timestamp);
+SQL
+
+      $query->execute;
+
+    $self->setRevision(9);
+}
+
+#######################################################################################
+# 
+# Create revision 10 of the database 
+#
+#######################################################################################
+sub createRevision_10 {
+    my ($self) = @_;
+
+    print "* Creating revision 10 of '$self->{_dbName}'\n";
+
+    my $query = $self->{_db}->prepare(<<SQL);
+    ALTER TABLE hosts 
+        ADD COLUMN writable TINYINT NOT NULL DEFAULT 0,
+        ADD COLUMN readable TINYINT NOT NULL DEFAULT 0;
+SQL
+
+    $query->execute;
+
+    $self->setRevision(10);
 }
 
Index: branches/eam_branches/ipp-20100621/tools/czartool/Czarplot.pm
===================================================================
--- branches/eam_branches/ipp-20100621/tools/czartool/Czarplot.pm	(revision 28794)
+++ branches/eam_branches/ipp-20100621/tools/czartool/Czarplot.pm	(revision 28980)
@@ -154,10 +154,57 @@
     my ($self, $minY, $maxY) = @_;
 
-    ${$maxY} = ${$maxY} + (${$maxY}/10);
-    ${$minY} = ${$minY} - (${$minY}/10);
+    my $tmp;
+    if (${$maxY} < ${$minY}) {
+
+        $tmp = ${$maxY};
+        ${$maxY} = ${$minY};
+        ${$minY} = $tmp;
+    }
+
+    my $border = (${$maxY} - ${$minY})/10;
+
+    ${$maxY} += $border;
+    ${$minY} -= $border ;
     if (${$maxY} == 0) {${$maxY} = 1;}
     if (${$minY} == 0) {${$minY} = -1;}
 }
 
+
+###########################################################################
+#
+# Figures out suitable spacing for time tics on time-series pliots
+#
+###########################################################################
+sub getTimeSpacing {
+    my ($self, $timeDiff, $divX, $timeFormat) = @_;
+
+    # if less than a couple of hour's data plotted, show 30 mins tics
+    if ($timeDiff < 7200) {
+        ${$timeFormat} = "%H:%M";
+        ${$divX} = 1800;
+    }
+    # if less than half a day's data plotted, show hourly tics
+    elsif ($timeDiff < 43200) {
+        ${$timeFormat} = "%H:%M";
+        ${$divX} = 3600;
+    }
+    # if less than one day's data plotted, show 2 hourly tics
+    elsif ($timeDiff < 86400) {
+        ${$timeFormat} = "%H:%M";
+        ${$divX} = 7200;
+    }
+    # if less than 1 week's data is data plotted, show daily tics
+    elsif ($timeDiff < 604800) {
+
+        ${$timeFormat} = "%m/%d";
+        ${$divX} = 86400;
+    }
+    else {
+
+        ${$timeFormat} = "%m/%d";
+        ${$divX} = 172800;
+    }
+}
+
 ###########################################################################
 #
@@ -171,30 +218,16 @@
 
     my $timeFormat = undef;
-
-    my $divX = $timeDiff/4;
-
-    # if less than a couple of hour's data plotted, show 30 mins tics
-    if ($timeDiff < 7200) {
-        $timeFormat = "%H:%M";
-        $divX = 1800;
-    }
-    # if less than half a day's data plotted, show hourly tics
-    elsif ($timeDiff < 43200) {
-        $timeFormat = "%H:%M";
-        $divX = 3600;
-    }
-    # if less than one day's data plotted, show 2 hourly tics
-    elsif ($timeDiff < 86400) {
-        $timeFormat = "%H:%M";
-        $divX = 7200;
-    }
-    # if more than one day's data plotted, show daily tics
-    else {
-        
-        $timeFormat = "%m/%d %H:%M";
-        $divX = 86400;
-    }
+    my $divX = undef;
+
+    $self->getTimeSpacing($timeDiff, \$divX, \$timeFormat);
 
     my $numOfPlots = keys %$gnuplotFiles;
+    my $title = undef;
+
+    # sort out plot title
+    if ($numOfPlots == 1) {foreach my $stage (keys %$gnuplotFiles) {$title = "'".$stage."'";}}
+    else {$title = "'All stages'"}
+
+    $title .= " for '$label', '$fromTime' to '$toTime'";
 
     open (GP, "|/usr/bin/gnuplot -persist") or die "no gnuplot";
@@ -205,8 +238,9 @@
         "set term $self->{_outputFormat};" .
         "set output \"$outputFile\";" .
-        "set title \"All stages for '$label' since $fromTime\";" .
+        "set title \"$title\";" .
         "set key left top;" .
         "set xdata time;" .
         "set timefmt \"$self->{_dateFormat}\";" .
+    #    "set yrange [\"$minY\":\"$maxY\"];" .
         "set xrange [\"$minX\":\"$maxX\"];" .
         "set format x \"$timeFormat\";" .
@@ -224,7 +258,7 @@
         if ($numOfPlots == 1) {
 
-            print GP "'" . $gnuplotFiles->{$stage} . "' using 1:4 title \"processed\" with lines lt 2,";
-            print GP "'" . $gnuplotFiles->{$stage} . "' using 1:2 title \"pending\" with lines lt 3,";
-            print GP "'" . $gnuplotFiles->{$stage} . "' using 1:3 title \"faults\" with lines lt 1";
+            print GP "'" . $gnuplotFiles->{$stage} . "' using 1:4 title \"Processed\" with lines lt 2,";
+            print GP "'" . $gnuplotFiles->{$stage} . "' using 1:2 title \"Pending\" with lines lt 4,";
+            print GP "'" . $gnuplotFiles->{$stage} . "' using 1:3 title \"Faults\" with lines lt 7";
         }
         # when plotting multiple stages, show only processed
@@ -241,9 +275,22 @@
 ###########################################################################
 #
-# Plots a histogram of processed stuff
-#
-###########################################################################
-sub plotHistogram {
-    my ($self, $inputFile, $outputFile, $label, $fromTime, $toTime) = @_;
+# Plots a time-series of cluster storage
+#
+###########################################################################
+sub plotStorageTimeSeries {
+    my ($self, $fromTime, $toTime) = @_;
+
+    my $prefix = $self->{_outputPath} ? $self->{_outputPath} : ".";
+    my $outputFile = "$prefix/czarplot_cluster.png";
+    my ($minX, $maxX, $minY, $maxY, $timeDiff);
+
+    my $gnuplotFile = $self->{_czarDb}->createStorageTimeSeriesData($fromTime, $toTime, \$minX, \$maxX, \$minY, \$maxY, \$timeDiff);
+
+    $self->sortOutMaxMinY(\$minY, \$maxY);
+
+    my $timeFormat = undef;
+    my $divX = undef;
+
+    $self->getTimeSpacing($timeDiff, \$divX, \$timeFormat);
 
     open (GP, "|/usr/bin/gnuplot -persist") or die "no gnuplot";
@@ -254,5 +301,39 @@
         "set term $self->{_outputFormat};" .
         "set output \"$outputFile\";" .
-        "set title \"Processing status for '$label' since $fromTime\";" .
+        "set title \"Total available cluster space over time\";" .
+        "set key left top;" .
+        "set xdata time;" .
+        "set timefmt \"$self->{_dateFormat}\";" .
+        "set xrange [\"$minX\":\"$maxX\"];" .
+        "set yrange [\"$minY\":\"$maxY\"];" .
+        "set format x \"$timeFormat\";" .
+        "set xtics \"$minX\", $divX, \"$maxX\";" .
+        "set grid xtics;" .
+        "set xlabel \"Time\";" .
+        "set ylabel \"Available (TB)\";" .
+        "plot " . 
+#        "'$gnuplotFile' using 1:2 title \"Total\" with lines lt 1," .
+        "'$gnuplotFile' using 1:2 title \"Available\" with lines lt 2\n";
+
+    print GP "\n";
+    close GP;
+}
+
+###########################################################################
+#
+# Plots a histogram of processed stuff
+#
+###########################################################################
+sub plotHistogram {
+    my ($self, $inputFile, $outputFile, $label, $fromTime, $toTime) = @_;
+
+    open (GP, "|/usr/bin/gnuplot -persist") or die "no gnuplot";
+    use FileHandle;
+    GP->autoflush(1);
+
+    print GP
+        "set term $self->{_outputFormat};" .
+        "set output \"$outputFile\";" .
+        "set title \"'$label', '$fromTime' to '$toTime'\";" .
         "set grid;" .
         "set boxwidth;" .
@@ -262,8 +343,51 @@
         "set bmargin 5;" .
         "set ylabel \"Exposures\";" .
-        "plot '$inputFile' using 2:xtic(1) title \"Processed\" lt 2, '' using 3 title \"Pending\" lt 3, '' using 4 title \"Faults\" lt 1\n";
+        "plot '$inputFile' using 2:xtic(1) title \"Processed\" lt 2, '' using 3 title \"Pending\" lt 4, '' using 4 title \"Faults\" lt 7;" . 
+        "\n";
 
     close GP;
 }
 
+###########################################################################
+#
+# Plots disk usage across cluster as a stacked histogram
+#
+###########################################################################
+sub plotDiskUsageHistogram {
+    my ($self) = @_;
+
+    my $prefix = $self->{_outputPath} ? $self->{_outputPath} : "."; # TODO should be function for this
+        my $outputFile = "$prefix/czarplot_hosts_space.png";
+    my $limit = 97.0;
+    my $inputFile = $self->{_czarDb}->createHostsData($limit);
+
+    my $totalUsed = $self->{_czarDb}->getTotalClusterStorageAsPercentage();
+
+    my $totalPercent = sprintf("%.1f%%", $totalUsed);
+
+    open (GP, "|/usr/bin/gnuplot -persist") or die "no gnuplot";
+    use FileHandle;
+    GP->autoflush(1);
+
+    print GP
+        "set term $self->{_outputFormat};" .
+        "set output \"$outputFile\";" .
+        "set title \"Nebulous disk use across IPP cluster ($totalPercent of total allocated)\";" .
+        "set style fill solid 1.00 border -1;" .
+        "set style histogram rowstacked;" .
+        "set style data histograms;" .
+        "set ylabel \"Space (TB)\";" .
+        "set xtic rotate by -90 scale 0;" .
+        "plot '$inputFile' " .
+        "using 2:xtic(1) t \"Used\" lt 7," .
+        "'' using 3 t \"Over $limit% used\" lt 1," . 
+        "'' using 4 t \"Unavailable\" fs solid 0.50 lt -1 ," . 
+        "'' using 5 t \"Free\" lt 2," . 
+        "'' using 6 notitle fs solid 0.50 lt -1" . 
+        ";" .
+
+        "\n";
+
+    close GP;
+}
 1;
Index: branches/eam_branches/ipp-20100621/tools/czartool/Gpc1Db.pm
===================================================================
--- branches/eam_branches/ipp-20100621/tools/czartool/Gpc1Db.pm	(revision 28794)
+++ branches/eam_branches/ipp-20100621/tools/czartool/Gpc1Db.pm	(revision 28980)
@@ -8,4 +8,32 @@
 use czartool::MySQLDb;
 our @ISA = qw(czartool::MySQLDb);    # inherits from MySQLDb
+
+###########################################################################
+#
+# Returns the right join table and ID to join on for for a given stage TODO make private
+#
+###########################################################################
+sub getJoinTableAndId {
+    my ($self, $stage, $joinTable, $id) = @_;
+
+    ${$id} = $stage."_id";
+
+    if ($stage eq "chip") {${$joinTable}="chipProcessedImfile";}
+    elsif ($stage eq "cam") {${$joinTable}="camProcessedExp";}
+    elsif ($stage eq "fake") {${$joinTable}="fakeProcessedImfile";}
+    elsif ($stage eq "warp") {${$joinTable}="warpSkyfile";}
+    elsif ($stage eq "stack") {${$joinTable}="stackSumSkyfile";}
+    elsif ($stage eq "diff") {${$joinTable}="diffSkyfile";}
+    elsif ($stage eq "magic") {${$joinTable}="magicNodeResult";}
+    elsif ($stage eq "magicDS") {${$id} = "magic_ds_id"; ${$joinTable}="magicDSFile";}
+    elsif ($stage eq "dist") {${$joinTable}="distComponent";}
+    else {
+
+        print "* ERROR: could nod find joinTable and ID for '$stage' stage\n";
+        return 0;
+    }
+
+    return 1;
+}
 
 ###########################################################################
@@ -30,5 +58,4 @@
 }
 
-
 ###########################################################################
 #
@@ -37,21 +64,11 @@
 ###########################################################################
 sub countFaults {
-    my ($self, $label, $stage) = @_;
+    my ($self, $label, $stage, $state) = @_;
 
-
-    my $table = getTableForStage($self, $stage);
-    my $joinTable;
-    my $id = $stage."_id";
-
-    if ($stage eq "chip") {$joinTable="chipProcessedImfile";}
-    elsif ($stage eq "cam") {$joinTable="camProcessedExp";}
-    elsif ($stage eq "fake") {$joinTable="fakeProcessedImfile";}
-    elsif ($stage eq "warp") {$joinTable="warpSkyfile";}
-    elsif ($stage eq "stack") {$joinTable="stackSumSkyfile";}
-    elsif ($stage eq "diff") {$joinTable="diffSkyfile";}
-    elsif ($stage eq "magic") {$joinTable="magicNodeResult";}
-    elsif ($stage eq "magicDS") {$id = "magic_ds_id"; $joinTable="magicDSFile";}
-    elsif ($stage eq "dist") {$joinTable="distComponent";}
-    else {return -1;}
+    my $table = undef;
+    my $joinTable = undef;
+    my $id = undef;
+    $table = getTableForStage($self, $stage);
+    if (!getJoinTableAndId($self, $stage, \$joinTable, \$id)) {return -1;}
 
     my $faultCol =  $joinTable.".fault";
@@ -64,5 +81,5 @@
         WHERE label LIKE '$label'
         AND $faultCol != 0
-        AND $stateCol = 'new'
+        AND $stateCol = '$state'
 SQL
 
@@ -85,5 +102,5 @@
 SQL
 
-        $query->execute;
+    $query->execute;
     my $priority = scalar $query->fetchrow_array();
     if (!$priority) {return 50000;} # assume labels not given priority in gpc1 Db have highest priority
@@ -100,15 +117,47 @@
 
     my $table = getTableForStage($self, $stage);
-    if ($state eq "fault") {return countFaults($stage);}
+    my $query = undef;
+
+    if ($state eq "update") {
+
+        if ($stage eq "dist") {return 0;}
+        my $joinTable = undef;
+        my $id = undef;
+        if (!getJoinTableAndId($self, $stage, \$joinTable, \$id)) {return -1;}
+
+        if ($stage eq "chip" || $stage eq "fake" || $stage eq "warp" || $stage eq "diff" || $stage eq "magicDS") {
+            $query = $self->{_db}->prepare(<<SQL);
+            SELECT COUNT(state)
+                FROM $table JOIN $joinTable 
+                USING($id) 
+                WHERE label LIKE '$label'
+                AND state = 'update' 
+                AND data_state = 'update';
+SQL
+        }
+        else {
+        
+            $query = $self->{_db}->prepare(<<SQL);
+            SELECT COUNT(state)
+                FROM $table JOIN $joinTable 
+                USING($id) 
+                WHERE label LIKE '$label'
+                AND state = 'update'; 
+SQL
+        }
+
+    }
+    else {
+
+        $query = $self->{_db}->prepare(<<SQL);
+        SELECT COUNT(state)  
+            FROM $table 
+            WHERE label LIKE '$label' 
+            AND state = '$state'
+SQL
+    }
 
 
-    my $query = $self->{_db}->prepare(<<SQL);
-    SELECT count(state)  
-        FROM $table 
-        WHERE label LIKE '$label' 
-        AND state = '$state'
-SQL
-
-        $query->execute;
+    $query->execute;
     return scalar $query->fetchrow_array();
 }
Index: branches/eam_branches/ipp-20100621/tools/czartool/Nebulous.pm
===================================================================
--- branches/eam_branches/ipp-20100621/tools/czartool/Nebulous.pm	(revision 28980)
+++ branches/eam_branches/ipp-20100621/tools/czartool/Nebulous.pm	(revision 28980)
@@ -0,0 +1,161 @@
+#!/usr/bin/perl -w
+
+use warnings;
+use strict;
+
+package czartool::Nebulous;
+
+###########################################################################
+#
+# Constructor TODO put in check that we can run nebulous
+#
+###########################################################################
+sub new {
+    my $class = shift;
+    my $self = {_czarDb => shift};
+
+    $self->{_totalAvail} = undef;
+    $self->{_totalUsed} = undef;
+    $self->{_totalUsedAsPercent} = undef;
+    $self->{_totalCluster} = undef;
+    $self->{_totalHosts} = undef;
+    $self->{_hostsOverNinetyEightPC} = undef;
+
+    bless $self, $class;
+    return $self;
+}
+
+###########################################################################
+#
+# Converts Kb to Tb 
+# 
+###########################################################################
+sub convertKbToTb {
+    my ($self, $Kb) = @_;
+
+    return $Kb/1073741824;
+}
+
+###########################################################################
+#
+# Returns total cluster usage as percentage
+#
+###########################################################################
+sub getTotalUsedAsPercentage {
+    my ($self) = @_;
+
+    return $self->{_totalUsedAsPercent};
+}
+
+###########################################################################
+#
+# Returns total cluster usage in T 
+#
+###########################################################################
+sub getTotalUsedInTb {
+    my ($self) = @_;
+
+    return $self->convertKbToTb($self->{_totalUsed});
+}
+
+###########################################################################
+#
+# Returns total cluster space in T 
+#
+###########################################################################
+sub getTotalClusterInTb {
+    my ($self) = @_;
+
+    return $self->convertKbToTb($self->{_totalCluster});
+}
+
+###########################################################################
+#
+# Returns total cluster available in T 
+#
+###########################################################################
+sub getTotalAvailInTb {
+    my ($self) = @_;
+
+    return $self->convertKbToTb($self->{_totalAvail});
+}
+
+###########################################################################
+#
+# Runs neb-df and puts output in gnuplot ready format 
+#
+###########################################################################
+sub updateClusterSpaceInfo {
+    my ($self) = @_;
+
+    my @cmdOut = `neb-df`;
+    my $line;
+    $self->{_totalHosts} = 0;
+    $self->{_hostsOverNinetyEightPC} = 0;
+    my $readable;
+    my $writable;
+    foreach $line (@cmdOut) {
+
+        chomp($line);
+        if ($line =~ m/.*Filesystem.*/i) {next;}
+        elsif ($line =~ m/.*summmary.*/i) {next;}
+        elsif ($line =~ m/.*total.*/i) {next;}
+        elsif ($line =~ m/\s+[0-9]+\s+([0-9]+)\s+([0-9]+)\s+.*allocated.*/i) {
+
+            $self->{_totalUsed} = $self->convertKbToTb($1);
+            $self->{_totalAvail} = $self->convertKbToTb($2);
+            $self->{_totalCluster} = $self->convertKbToTb($1 + $2);
+            $self->{_totalUsedAsPercent} = ($self->{_totalUsed}/$self->{_totalCluster})*100;
+
+            next;
+        }
+        elsif ($line =~ m/(ipp[0-9]+)\s.+[0-9]+\s+([0-9]+)\s+([0-9]+)\s+([0-9]+)%.*/i) {
+        
+            $self->{_totalHosts}++;
+            if ($4 >= 98) {$self->{_hostsOverNinetyEightPC}++;}
+
+            $self->getReadableWritableStatus($1, \$readable, \$writable);
+
+            $self->{_czarDb}->updateHost($1, 
+                    $self->convertKbToTb($2+$3), 
+                    $self->convertKbToTb($3), 
+                    $self->convertKbToTb($2), 
+                    $readable, $writable);
+        }
+    }
+
+    $self->{_czarDb}->insertNewClusterSpace(
+            $self->{_totalCluster}, 
+            $self->{_totalAvail},  
+            $self->{_totalUsed}, 
+            $self->{_hostsOverNinetyEightPC});
+}
+
+###########################################################################
+#
+# Runs neb-host and readable/writable status for this host 
+#
+###########################################################################
+sub getReadableWritableStatus {
+    my ($self, $host, $readable, $writable) = @_;
+
+    ${$readable} = 0;
+    ${$writable} = 0;
+
+    my @cmdOut = `neb-host`;
+    my $line;
+    foreach $line (@cmdOut) {
+
+        chomp($line);
+        if ($line =~ m/$host\s+[0-9.A-Za-z]+\s+([01]+)\s+([01]+)\s+([01]+)\s+.*/i) {
+
+            # if mounted...
+            if ($1) {
+
+                ${$readable} = $3;
+                ${$writable} = $2;
+            }
+        }
+    }
+}
+1;
Index: branches/eam_branches/ipp-20100621/tools/czartool/Pantasks.pm
===================================================================
--- branches/eam_branches/ipp-20100621/tools/czartool/Pantasks.pm	(revision 28794)
+++ branches/eam_branches/ipp-20100621/tools/czartool/Pantasks.pm	(revision 28980)
@@ -5,5 +5,4 @@
 
 package czartool::Pantasks;
-
 
 my @servers = (
@@ -21,4 +20,16 @@
         );
 
+###########################################################################
+#
+# Constructor TODO put in check that we can run pantasks_client
+#
+###########################################################################
+sub new {
+    my $class = shift;
+    my $self = {};
+
+    bless $self, $class;
+    return $self;
+}
 
 ###########################################################################
@@ -35,17 +46,4 @@
 ###########################################################################
 #
-# Constructor
-#
-###########################################################################
-sub new {
-    my $class = shift;
-    my $self = {};
-
-    bless $self, $class;
-    return $self;
-}
-
-###########################################################################
-#
 # Returns the correct server for this processing stage 
 #
@@ -58,4 +56,22 @@
 }
 
+###########################################################################
+#
+# Checks for a meaningful response from pantasks client 
+#
+###########################################################################
+sub outputOk {
+    my ($self, $output) = @_;
+
+    if (
+            $output =~ m/.*show\.labels.*/i ||
+            $output =~ m/.*Connection reset by peer.*/i ||
+            $output =~ m/.*server is busy.*/i ) { 
+
+        print "* WARNING: pantasks returned '$output'\n";
+        return 0;
+    }
+    return 1;
+}
 
 ###########################################################################
@@ -75,18 +91,6 @@
 
         chomp($line);
-        if ($line =~ m/pantasks:\s+(.*)/) {
-
-            # HACK quit if we get 'show.labels: Command not found.'
-            if ($1 =~ m/.*show\.labels.*/i) {return \@labels;};
-            # HACK quit if we get 'Connection reset by peer'
-            if ($1 =~ m/.*Connection reset by peer.*/i) {return \@labels;};
-            # HACK quit if we get 'server is busy' message
-            if ($1 =~ m/.*server is busy.*/i) {return \@labels;};
-            # HACK to get around 'dummy' label in stdscience
-            if ($1 !~ m/.*dummy.*/) {push(@labels, $1);};
-            $passedHeader=1; 
-            next;
-        }
-
+        if (!$self->outputOk($line)) {return \@labels;}
+        if ($line =~ m/pantasks:\s+/) {$passedHeader=1; next;}
         if ($passedHeader) {push(@labels, $line);}
     }
@@ -113,5 +117,4 @@
         if ($line =~ m/Scheduler is running/) {${$running} = 1; ${$alive}=1;last;}
         if ($line =~ m/Task Status/) {last;}
-
     }
 }
@@ -125,15 +128,38 @@
     my ($self, $server) = @_;
 
+    my @cmdOut = `echo "status;quit" | pantasks_client -c ~ipp/$server/ptolemy.rc 2>&1`;
+    my $line;
+    my $passedHeader=0;
+    print "\n";
+    foreach $line (@cmdOut) {
+
+        if ($line =~ m/.*Task Status.*/) {$passedHeader=1;next;}
+        if ($passedHeader){print "$line";}
+    }
+}
+
+###########################################################################
+#
+# Gets revert status for this stage 
+#
+###########################################################################
+sub getRevertStatus {
+    my ($self, $stage, $reverting) = @_;
+
+    my $server = $self->getServerForThisStage($stage);
+
+    if ($stage eq "cam") {$stage = "camera";}
 
     my @cmdOut = `echo "status;quit" | pantasks_client -c ~ipp/$server/ptolemy.rc 2>&1`;
     my $line;
-    my $passedHeader=0;
     foreach $line (@cmdOut) {
 
         chomp($line);
-        if ($line =~ m/.*Task Status.*/) {$passedHeader=1;next;}
-        if ($passedHeader){print "$line<br>";}
+        if ($line =~ m/\s+([+-])[+-]\s+$stage\.revert.*/) {
+
+            if ($1 =~ m/-/) {${$reverting} = 0;}
+            elsif ($1 =~ m/\+/) {${$reverting}=1;}
+        }
     }
 }
-
-
+1;
