Commit ff96cb1a authored by Mike Hibler's avatar Mike Hibler

Add sort and limit options.

parent a7bdf7a9
...@@ -34,18 +34,21 @@ my $epoch = 1105563540; ...@@ -34,18 +34,21 @@ my $epoch = 1105563540;
sub usage { sub usage {
print("Usage: $0 [-ARalrsvw] [node ...]\n". print("Usage: $0 [-ARalrsvw] [node ...]\n".
" -A print history of all nodes (you do NOT want to do this)\n". " -A print history of all nodes (you do NOT want to do this)\n".
" -R print raw records (default is to combine some records)\n". " -R print raw records (default is to combine some records)\n".
" -a show only when allocated to experiment\n". " -S field sort list by field (date, node, pideid, uid, elapsed)\n".
" -l list records\n". " -a show only when allocated to experiment\n".
" -r reverse order (most recent first)\n". " -l list records\n".
" -s show a summary of node's past usage\n". " -n num report on only the first num records (after sorting)\n".
" -v verbose output\n". " use negative value for last num records\n".
" -w print warnings about anomolous records\n"); " -r reverse order (most recent first)\n".
" -s show a summary of node's past usage\n".
" -v verbose output\n".
" -w print warnings about anomolous records\n");
exit(1); exit(1);
} }
my $optlist = "ARalrswv"; my $optlist = "ARS:aln:rswv";
my $warnme = 0; my $warnme = 0;
my $verbose = 0; my $verbose = 0;
my $showall = 0; my $showall = 0;
...@@ -53,8 +56,46 @@ my $showalloconly = 0; ...@@ -53,8 +56,46 @@ my $showalloconly = 0;
my $list = 0; my $list = 0;
my $summary = 0; my $summary = 0;
my $raw = 0; my $raw = 0;
my $numrecs = 0;
#
# Sort stuff. sortby value should correspond to record field format:
#
# sortby 0: node
# sortby 1: pideid
# sortby 2: uid
# sortby 3: date
# sortby 4: elapsed
#
my %sortmap = (
"node" => 0,
"pideid" => 1,
"uid" => 2,
"date" => 3,
"elapsed" => 4
);
my $sortbydate = $sortmap{date};
my $sortby = $sortbydate;
my $revorder = 0; my $revorder = 0;
# Sort function: first by indicated field, secondarily by date
sub byfield()
{
# already sorted by date
return 0 if ($sortby == $sortbydate);
# int compare for elapsed
if ($sortby == $sortmap{elapsed}) {
return @$a[$sortby] <=> @$b[$sortby] ||
@$a[$sortbydate] <=> @$b[$sortbydate];
}
# string compare for everything else
return @$a[$sortby] cmp @$b[$sortby] ||
@$a[$sortbydate] <=> @$b[$sortbydate];
}
# #
# Parse command arguments. # Parse command arguments.
# #
...@@ -68,12 +109,22 @@ if (defined($options{"A"})) { ...@@ -68,12 +109,22 @@ if (defined($options{"A"})) {
if (defined($options{"R"})) { if (defined($options{"R"})) {
$raw = 1; $raw = 1;
} }
if (defined($options{"S"})) {
if (!defined($sortmap{$options{"S"}})) {
print STDERR "invalid sort field '$options{S}'\n";
usage();
}
$sortby = $sortmap{$options{"S"}};
}
if (defined($options{"a"})) { if (defined($options{"a"})) {
$showalloconly = 1; $showalloconly = 1;
} }
if (defined($options{"l"})) { if (defined($options{"l"})) {
$list = 1; $list = 1;
} }
if (defined($options{"n"})) {
$numrecs = $options{"n"};
}
if (defined($options{"r"})) { if (defined($options{"r"})) {
$revorder = 1; $revorder = 1;
} }
...@@ -119,8 +170,7 @@ my $query_result = ...@@ -119,8 +170,7 @@ my $query_result =
"$querymod $orderby"); "$querymod $orderby");
my %nodeinfo; # [ expt, starttime, uid ] my %nodeinfo; # [ expt, starttime, uid ]
my %nodestats; # [ free, allocated, reloading, down ] my @records;
my @lines;
while (my %row = $query_result->fetchhash()) { while (my %row = $query_result->fetchhash()) {
my $pideid = "$row{pid}/$row{eid}"; my $pideid = "$row{pid}/$row{eid}";
...@@ -133,26 +183,19 @@ while (my %row = $query_result->fetchhash()) { ...@@ -133,26 +183,19 @@ while (my %row = $query_result->fetchhash()) {
# from the epoch til now. # from the epoch til now.
# #
if (!defined($nodeinfo{$node})) { if (!defined($nodeinfo{$node})) {
$nodeinfo{$node} = [ "FREE", $epoch, "root" ]; $nodeinfo{$node} = [ "", $epoch, "root" ];
}
if (!defined($nodestats{$node})) {
$nodestats{$node} = [ 0, 0, 0, 0 ];
} }
my ($opideid, $ostamp, $ouid) = @{$nodeinfo{$node}}; my ($opideid, $ostamp, $ouid) = @{$nodeinfo{$node}};
my $elapsed = $stamp - $ostamp; my $elapsed = $stamp - $ostamp;
my $start = ctime($ostamp);
my $end = ctime($stamp);
chomp($start);
chomp($end);
# #
# Allocating node to experiment. # Allocating node to experiment.
# Should currently be free. # Should currently be free.
# #
if ($row{op} eq "alloc") { if ($row{op} eq "alloc") {
if ($opideid ne "FREE") { if ($opideid ne "") {
print STDERR "$node: dup alloc: already in $opideid at $start\n" print STDERR "$node: dup alloc: already allocated to $opideid\n"
if ($warnme); if ($warnme);
# XXX possibly missing state in the DB, treat as move # XXX possibly missing state in the DB, treat as move
} }
...@@ -167,7 +210,7 @@ while (my %row = $query_result->fetchhash()) { ...@@ -167,7 +210,7 @@ while (my %row = $query_result->fetchhash()) {
print STDERR "$node: mismatched alloc,free records: $opideid,$pideid\n" print STDERR "$node: mismatched alloc,free records: $opideid,$pideid\n"
if ($warnme); if ($warnme);
} }
$nodeinfo{$node} = [ "FREE", $stamp, $uid ]; $nodeinfo{$node} = [ "", $stamp, $uid ];
} }
elsif ($row{op} eq "move") { elsif ($row{op} eq "move") {
if (!$raw) { if (!$raw) {
...@@ -181,53 +224,55 @@ while (my %row = $query_result->fetchhash()) { ...@@ -181,53 +224,55 @@ while (my %row = $query_result->fetchhash()) {
$nodeinfo{$node} = [ $pideid, $stamp, $uid ]; $nodeinfo{$node} = [ $pideid, $stamp, $uid ];
} }
my ($ftime, $atime, $rtime, $dtime) = @{$nodestats{$node}}; # save off the record
my $isalloced = 0; push(@records, [ $node, $opideid, $ouid, $ostamp, $elapsed ]);
if ($opideid eq "FREE") {
$ftime += $elapsed;
} elsif ($opideid eq "emulab-ops/reloadpending" ||
$opideid eq "emulab-ops/reloading") {
$rtime += $elapsed;
} elsif ($opideid eq "emulab-ops/hwdown") {
$dtime += $elapsed;
} else {
$atime += $elapsed;
$isalloced = 1;
}
$nodestats{$node} = [ $ftime, $atime, $rtime, $dtime ];
if ($list) {
if ($verbose) {
my $str="$node: $opideid from $start til $end ($elapsed sec)\n";
push(@lines, $str)
if (!$showalloconly || $isalloced);
} else {
my ($pid, $eid) = split("/", $opideid);
$eid = "FREE"
if ($pid eq "FREE");
my $str="$node REC $ostamp $elapsed $uid $pid $eid\n";
push(@lines, $str)
if (!$showalloconly || $isalloced);
}
}
} }
# Include the current state of nodes # Include the current state of nodes in a final record
my $stamp = time(); my $stamp = time();
for $node (keys(%nodeinfo)) { for $node (keys(%nodeinfo)) {
my ($opideid, $ostamp, $ouid) = @{$nodeinfo{$node}}; my ($opideid, $ostamp, $ouid) = @{$nodeinfo{$node}};
my $elapsed = $stamp - $ostamp; my $elapsed = $stamp - $ostamp;
my $start = ctime($ostamp); push(@records, [ $node, $opideid, $ouid, $ostamp, $elapsed ]);
chomp($start); }
# Prune the list based on date range (someday)
# Sort the list as desired
if ($sortby ne "date") {
@records = sort byfield @records;
}
if ($revorder) {
@records = reverse(@records);
}
# Prune to the proper number of entries (first/last $numrecs entries)
if ($numrecs && $numrecs < $#records) {
if ($numrecs > 0) {
@records = @records[0 .. $numrecs-1];
} else {
@records = @records[$numrecs .. -1 ];
}
}
#
# Loop over the remaining records, computing summary stats
# and printing (if desired).
#
for my $rec (@records) {
my ($node, $pideid, $uid, $stamp, $elapsed) = @{$rec};
if (!defined($nodestats{$node})) {
$nodestats{$node} = [ 0, 0, 0, 0 ];
}
my ($ftime, $atime, $rtime, $dtime) = @{$nodestats{$node}}; my ($ftime, $atime, $rtime, $dtime) = @{$nodestats{$node}};
my $isalloced = 0; my $isalloced = 0;
if ($opideid eq "FREE") { if ($pideid eq "") {
$ftime += $elapsed; $ftime += $elapsed;
} elsif ($opideid eq "emulab-ops/reloadpending" || } elsif ($pideid eq "emulab-ops/reloadpending" ||
$opideid eq "emulab-ops/reloading") { $pideid eq "emulab-ops/reloading") {
$rtime += $elapsed; $rtime += $elapsed;
} elsif ($opideid eq "emulab-ops/hwdown") { } elsif ($pideid eq "emulab-ops/hwdown") {
$dtime += $elapsed; $dtime += $elapsed;
} else { } else {
$atime += $elapsed; $atime += $elapsed;
...@@ -237,27 +282,30 @@ for $node (keys(%nodeinfo)) { ...@@ -237,27 +282,30 @@ for $node (keys(%nodeinfo)) {
if ($list) { if ($list) {
if ($verbose) { if ($verbose) {
my $str = "$node: $opideid from $start til NOW ($elapsed sec)\n"; my $start = ctime($stamp);
push(@lines, $str) chomp($start);
my $end = ctime($stamp + $elapsed);
chomp($end);
print "$node: $pideid from $start til $end ($elapsed sec)\n"
if (!$showalloconly || $isalloced); if (!$showalloconly || $isalloced);
} else { } else {
my ($pid, $eid) = split("/", $opideid); my ($pid, $eid);
$eid = "FREE" if ($pideid eq "") {
if ($pid eq "FREE"); $pid = $eid = "<FREE>";
my $str="$node REC $ostamp $elapsed $ouid $pid $eid\n"; } else {
push(@lines, $str) ($pid, $eid) = split("/", $pideid);
}
print "$node REC $stamp $elapsed $uid $pid $eid\n"
if (!$showalloconly || $isalloced); if (!$showalloconly || $isalloced);
} }
} }
} }
# Print out list #
if ($revorder) {
@lines = reverse(@lines);
}
print @lines;
# Print out summary information # Print out summary information
# We can do this for all nodes, but how do we present it?
#
my $node = $nodes[0]; # XXX my $node = $nodes[0]; # XXX
if ($summary && defined($nodestats{$node})) { if ($summary && defined($nodestats{$node})) {
my ($ftime, $atime, $rtime, $dtime) = @{$nodestats{$node}}; my ($ftime, $atime, $rtime, $dtime) = @{$nodestats{$node}};
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment