|
From: Peter P. <pr...@us...> - 2007-02-21 15:40:58
|
Update of /cvsroot/pyxida/Pyxida/web/bin In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv7508/web/bin Added Files: proxy.pl query.pl Aux.pm animateNC.pl Log Message: Made a new Pyxida release 0.1.4 --- NEW FILE: proxy.pl --- #!/usr/bin/perl use strict; use Getopt::Std; use Frontier::Client; use Data::Dumper; my $usage = "proxy.pl [options] url\n"; $usage .= " -c remote-node -l lease: create proxy coord for remote node with lease\n"; $usage .= " -d remote-node: destroy proxy coord for remote node\n"; $usage .= " -r remote-node -l lease: renew lease for this proxy coord\n"; $usage .= "\n"; $usage .= "proxy.pl -c www.google.com -l 3600000 http://righthand.eecs.harvard.edu:55501\n"; my %para = (); getopts('c:d:r:l:', \%para); ############################################################ if ($#ARGV < 0) { die ("Missing arguments\n$usage"); } my $url = $ARGV[0]; if ($url !~ /^http:\/\/.*?:\d+$/) { die ("bad url: $url\n$usage\n"); } ############################################################ my $server = Frontier::Client->new(url=>"$url"); my $lease = 3600000; if (defined($para{'l'})) { $lease = $para{'l'}; } if (defined($para{'c'})) { my $res = $server->call("pyxida.createProxyCoord",$para{'c'},$lease); print Dumper($res); #&outputBoolean($res); } elsif (defined($para{'d'})) { my $res = $server->call("pyxida.destroyProxyCoord",$para{'d'}); print Dumper($res); #&outputBoolean($res); } elsif (defined($para{'r'})) { my $res = $server->call("pyxida.renewProxyCoord",$para{'r'},$lease); print Dumper($res); #&outputBoolean($res); } else { die ("Missing arguments\n$usage"); } ############################################################ sub outputBoolean { my ($res) = @_; #print Dumper($res); #&Aux::printHash($hash); my $success = $res->value; if ($success == 1) { print "Success\n"; } else { print "Failure\n"; } } --- NEW FILE: Aux.pm --- package Aux; use strict; # subroutine name: max # Input: number1, number2 # returns greater of 2 numbers sub max { if ($_[0]<$_[1]) {return $_[1]} else {return $_[0]}; } sub name_value_pairs { my ($line, $hash, $btw_name_value, $btw_pairs) = @_; #print "line $line\n"; my @items = split (/(\w+)=/,$line); for (my $i = 1; $i <= $#items; $i+=2) { my $value = $items[$i+1]; $value =~ s/$btw_pairs$//; #print "$items[$i] = $value\n"; $hash->{$items[$i]} = $value; } } sub slurp_map { my ($filename, $map, $column) = @_; open IN, $filename or die ("Cannot open $filename"); while (my $line = <IN>) { if ($line =~ /^(.*?)\s+(.*?)$/) { if ($column == 1) { $map->{$1} = $2; } elsif ($column == 2) { $map->{$2} = $1; } else { die ("Column must be 1 or 2"); } } else { die ("Line in $filename did not match"); } } close IN; } sub slurp_hash_pair { my ($filename, $map, $keyColumn, $valueColumn) = @_; open IN, $filename or die ("Cannot open $filename"); while (my $line = <IN>) { my (@items) = split (/\s+/,$line); my $key = $items[$keyColumn]; my $value = $items[$valueColumn]; if (defined ($key) && defined($value)) { # print "adding k $key v $value\n"; $map->{$key} = $value; } } close IN; } sub slurp_column_to_hash { my ($filename, $hash, $column) = @_; open IN, $filename or die ("Cannot open $filename"); while (my $line = <IN>) { my (@items) = split (/\s+/,$line); if (defined ($items[$column])) { $hash->{$items[$column]} = 1; } } close IN; } sub slurp_columns_to_hash_pair { my ($filename, $hash, $columnA, $columnB, $num_columns) = @_; open IN, $filename or die ("Cannot open $filename"); while (my $line = <IN>) { my (@items) = split (/\s+/,$line); my $val = ''; my $not_defined = 0; if (defined($items[$columnA])) { for (my $i = $columnB; $i <= $num_columns; $i++) { if (defined($items[$i])) { $val .= $items[$i]; if ($i != $num_columns) { $val .= ' '; } } else { $not_defined = 1; } } $hash->{$items[$columnA]} = $val; } } close IN; } sub slurp_column_to_hash_pair { my ($filename, $hash, $columnA, $columnB) = @_; open IN, $filename or die ("Cannot open $filename"); while (my $line = <IN>) { my (@items) = split (/\s+/,$line); if (defined ($items[$columnA]) && defined ($items[$columnB])) { $hash->{$items[$columnA]} = $items[$columnB]; } } close IN; } sub slurp_column_to_array { my ($filename, $array, $column) = @_; open IN, $filename or die ("Cannot open $filename"); while (my $line = <IN>) { my (@items) = split (/\s+/,$line); if (defined ($items[$column])) { $array->[$#$array+1] = $items[$column]; } } close IN; } sub slurp_array_to_hash { my ($filename, $map, $keyColumn, $firstArrayElement, $distance) = @_; # i.e. read: key [foo1a foo1b] [foo2a foo2b] # return key-> array of foo1a, foo2a # with 0, 1, 2 open IN, $filename or die ("Cannot open $filename"); while (my $line = <IN>) { my (@items) = split (/\s+/,$line); my $key = $items[$keyColumn]; my @elements = (); # read every other element, which is the feed's id for (my $i = $firstArrayElement; $i <= $#items; $i+=$distance) { $elements[$#elements+1] = $items[$i]; } $map->{$key} = \@elements; } close IN; } sub slurp_file { my ($filename, $lines) = @_; open IN, $filename or die ("Cannot open $filename"); while (my $line = <IN>) { #$line =~ s/\s//g; chop ($line); $lines->[$#$lines+1] = $line; } close IN; } sub slurp_file_to_scalar { my ($filename) = @_; my $contents = ''; open IN, $filename or die ("Cannot open $filename"); while (my $line = <IN>) { $contents .= $line; } close IN; return $contents; } sub slurp_directory { my ($dirname, $files, $regex) = @_; opendir INDIR, $dirname or die ("Cannot open $dirname"); my (@allfiles) = readdir (INDIR); closedir INDIR; #print "$dirname $#allfiles\n"; foreach my $file (@allfiles) { #print "$file\n"; if ($file =~ /$regex/) { $files->[$#$files+1] = $file; } } } my $ALPHA = 0.1; sub remember_ewma { my ($hash, $key, $val) = @_; if (!defined($hash->{$key})) { $hash->{$key} = $val; } else { my $curr = $hash->{$key}; $hash->{$key} = ($ALPHA*$val)+((1.-$ALPHA)*$curr); } } sub remember_all { my ($hash, $key, $val) = @_; if (!defined($hash->{$key})) { my @v = (); $hash->{$key} = \@v; } my $vals = $hash->{$key}; $vals->[$#$vals+1] = $val; } sub recall_all { my ($hash, $key) = @_; if (!defined($hash->{$key})) { return undef; } my $vals = $hash->{$key}; return $vals; } sub recall_all_to_string { my ($hash, $key) = @_; my $str = ''; if (!defined($hash->{$key})) { return ''; } my $vals = $hash->{$key}; for (my $i = 0; $i <= $#$vals; $i++) { $str .= $vals->[$i]; if ($i != $#$vals) { $str .= ' '; } } return $str; } sub printHash { my ($hash) = @_; foreach my $key (keys %$hash) { print "$key->".$hash->{$key}."\n"; } } 1; --- NEW FILE: animateNC.pl --- #!/usr/bin/perl -w # This script creates an animation from a Pyxida log server log. # # Todos: # # * add proper conversion routing from 4D -> 3D # * add a more intelligent range calculation when choosing what to display # use strict; use Getopt::Std; use IPC::Open2; use Statistics::Descriptive; use Aux; my $framePeriod = 120; # frame period in sec my $debug = 0; my $frameFormat = "png"; my $codec = "ffv1"; my $fps = 25; my $rangePercentile = 99; my $alpha = 0.01; my $showShadows = 0; my $zoffset = 100; ###################################################################### my %params = (); my %pos = (); getopts("f:dSAc:a:", \%params); my $coordType; $coordType = "S" if defined $params{'S'}; $coordType = "A" if defined $params{'A'}; &usage unless $coordType; sub usage() { print << "EOF"; usage: cat <pyxida-serverlog.log> | animateNC.pl [-f sec] [-d] <-S|-A> -S : Use system-level coordinates -A : Use application-level coordinates -f : Frame perdiod in seconds -d : Turn on debug mode -c : cn2rgb file -a : id2asn file EOF die; } $framePeriod = $params{'f'} if defined $params{'f'}; $debug = 1 if defined $params{'d'}; ###################################################################### # slurp color files my %cn2color = (); my %id2cn = (); my $cn2color_file = 'data/animate/cn2rgb'; if (defined($params{'c'})) { $cn2color_file = $params{'c'}; } my $id2cn_file = 'data/animate/id2asn'; if (defined($params{'a'})) { $id2cn_file = $params{'a'}; } my %noColorFound = (); &Aux::slurp_columns_to_hash_pair ($cn2color_file,\%cn2color, 0, 1, 3); # hostname -> country &Aux::slurp_column_to_hash_pair ($id2cn_file,\%id2cn, 3, 2); # ip -> country &Aux::slurp_column_to_hash_pair ($id2cn_file,\%id2cn, 4, 2); ###################################################################### my $startFrameTS; my $frameCounter = 0; my $xrange, my $yrange, my $zrange; &clearRange(); my $s_xmin = 0; my $s_xmax = 0; my $s_ymin = 0; my $s_ymax = 0; my $s_zmin = 0; my $s_zmax = 0; local (*GPIN, *GPOUT); open2(\*GPIN, \*GPOUT, "gnuplot"); #open GPOUT, ">/tmp/gp.test" or die ("Cannot open gp.test"); print STDERR "Launching gnuplot...\n" if ($debug); while (my $line = <>) { if ($line =~ m/\w\w (\d+) \S+ a=(\S+) .+ sc2=\[(.+),(.+),(.+),h(.+)\] ac2=\[(.+),(.+),(.+),h(.+)\]/) { my ($ts, $addr) = ($1 / 1000, $2); my @sc = ($3, $4, $5, $6); my @ac = ($7, $8, $9, $10); my $dateTS = localtime($ts); print STDERR $line if ($debug); print STDERR "$dateTS $ts $addr " . join(",", @sc) . " " . join (",", @ac) . "\n" if ($debug); print STDERR "\nsc=" . join(" ", @sc) . "\n" if ($debug); print STDERR "ac=" . join(" ", @ac) . "\n\n" if ($debug); my @newCoord = (); if ($coordType eq 'S') { @newCoord = @sc; } else { @newCoord = @ac; } my $coordStr = join("", @newCoord); #print STDERR "$coordStr\n"; if ($coordStr =~ m/,/) { print STDERR "Found bad coordinate. Skiping.\n" if ($debug); next; } @newCoord = &projectSimple(@newCoord); $pos{$addr} = [ @newCoord ]; print STDERR "3D: " . join(" ", @{$pos{$addr}}) . "\n" if ($debug); &updateRange($pos{$addr}); $startFrameTS = $ts unless defined $startFrameTS; if ($ts - $startFrameTS > $framePeriod) { print STDERR "Outputting frame\n" if ($debug); $frameCounter++; &outputFrame($dateTS); %pos = (); &clearRange(); $startFrameTS = $ts; print STDERR "Starting a new frame at " . $dateTS . "\n"; } } } close GPIN; close GPOUT; #warn ("Not generating animation"); #exit (0); print STDERR "Generating animation...\n"; system "mencoder \"mf:///tmp/*.png\" -mf fps=$fps -o pyxida-anim-$coordType.avi -ovc lavc -lavcopts vcodec=$codec"; print STDERR "Deleting frames...\n"; system "rm /tmp/pyxida-anim-*.$frameFormat\n"; print STDERR "Done.\n"; sub outputFrame() { my $title = shift; my $filenameCount = &fixedNum($frameCounter); print GPOUT "set terminal $frameFormat size 1024,768\n"; print GPOUT "set output \'/tmp/pyxida-anim-$filenameCount.$frameFormat\'\n"; print GPOUT "set title \'$title\'\n"; print GPOUT << "EOF"; set grid nopolar set grid xtics nomxtics ytics nomytics noztics nomztics nox2tics nomx2tics noy2tics nomy2tics nocbtics nomcbtics set grid layerdefault EOF my $xmin = $xrange->percentile(100 - $rangePercentile); $xmin = 0 unless defined $xmin; my $xmax = $xrange->percentile($rangePercentile); $xmax = 0 unless defined $xmax; my $ymin = $yrange->percentile(100 - $rangePercentile); $ymin = 0 unless defined $ymin; my $ymax = $yrange->percentile($rangePercentile); $ymax = 0 unless defined $ymax; my $zmin = $zrange->percentile(100 - $rangePercentile); $zmin = 0 unless defined $zmin; my $zmax = $zrange->percentile($rangePercentile); $zmax = 0 unless defined $zmax; $s_xmin = $xmin unless defined $s_xmin; $s_xmax = $xmax unless defined $s_xmax; $s_ymin = $ymin unless defined $s_ymin; $s_ymax = $ymax unless defined $s_ymax; $s_zmin = $zmin unless defined $s_zmin; $s_zmax = $zmax unless defined $s_zmax; $s_xmin = (1 - $alpha) * $s_xmin + ($alpha * $xmin); $s_xmax = (1 - $alpha) * $s_xmax + ($alpha * $xmax); $s_ymin = (1 - $alpha) * $s_ymin + ($alpha * $ymin); $s_ymax = (1 - $alpha) * $s_ymax + ($alpha * $ymax); $s_zmin = (1 - $alpha) * $s_zmin + ($alpha * $zmin); $s_zmax = (1 - $alpha) * $s_zmax + ($alpha * $zmax); #for (my $i = 0; $i < 100; $i++) { # print "$i " . $xrange->percentile($i) . "\n"; #} print STDERR "[$s_xmin:$s_xmax] [$s_ymin:$s_ymax] [$s_zmin:$s_zmax]\n" if ($debug); print GPOUT "set xrange [$s_xmin:$s_xmax]\n"; print GPOUT "set yrange [$s_ymin:$s_ymax]\n"; print GPOUT "set zrange [" . ($s_zmin - $zoffset) . ":$s_zmax]\n"; print GPOUT 'rgb(r,g,b) = 65536 * int(r) + 256 * int(g) + int(b)'."\n"; # XXX where should shadow be print GPOUT "flat(p) = ".($s_zmin - $zoffset + 10)."\n"; #print GPOUT "set pointsize 1.5\n"; #print GPOUT "splot '-' notitle\n"; # notitle? print GPOUT "splot '-' " . 'using 1:2:3:(rgb($4,$5,$6)) notitle with points pt 7 lc rgb variable'; if ($showShadows) { print GPOUT ", '-' ".'using 1:2:(flat($3)) '."notitle with points lc \"#CCCCCC\"\n"; } else { print GPOUT "\n"; } my $shadow = ''; foreach my $addr (keys %pos) { print STDERR "$addr\n" if ($debug); my $points = join(" ", @{$pos{$addr}}); $shadow .= "$points\n"; $addr =~ s/\///g; $addr =~ s/:\d*//g; $addr = lc($addr); my $color = &getColor($addr); print GPOUT "$points $color\n"; #print "$points $color\n"; } print GPOUT "e\n"; print GPOUT "$shadow"."e\n" if ($showShadows); } sub updateRange() { my $coords = shift; print STDERR "Updating range $$coords[0]\n" if ($debug); $xrange->add_data($$coords[0]); $yrange->add_data($$coords[1]); $zrange->add_data($$coords[2]); } sub clearRange() { $xrange = new Statistics::Descriptive::Full->new(); $yrange = new Statistics::Descriptive::Full->new(); $zrange = new Statistics::Descriptive::Full->new(); } sub fixedNum() { my $num = shift; my $result = sprintf("%05d", $num); return $result; } #sub projectClever4D() { # my @coord4D = @_; # print STDERR "4D: $coord4D[0] $coord4D[1] $coord4D[2] $coord4D[3]\n" if ($debug); # # # x' = k * (x / w) # # y' = k * (y / w) # # z' = k * (z / w) # # my @coord3D = (); # if ($coord4D[3] == 0) { # @coord3D = (0, 0, 0); # } else { # @coord3D = ( $k * $coord4D[0] / $coord4D[3], $k * $coord4D[1] / $coord4D[3], $k * $coord4D[2] / $coord4D[3] ); # } # return @coord3D; #} sub projectSimple() { my @coord3Dh = @_; print STDERR "3D+h: $coord3Dh[0] $coord3Dh[1] $coord3Dh[2] $coord3Dh[3]\n" if ($debug); my @coord3D = ($coord3Dh[0], $coord3Dh[1], $coord3Dh[2]); return @coord3D; } ###################################################################### sub getColor { my ($host) = @_; #print "h $host\n"; #print "id $id2cn{$host}\n"; #print "cn $cn2color{$id2cn{$host}}\n"; #exit (0); my $color = ''; # hack around unknown hosts my $cn = ''; if (defined($id2cn{$host})) { $cn = $id2cn{$host}; } else { # try to match the country if ($host =~ /\.(\w*)$/) { $cn = $1; if ($cn =~ /edu/i) { $cn = 'US'; } $cn = uc($cn); } } if (defined($cn2color{$cn})) { $color = $cn2color{$cn}; } else { if (!defined($noColorFound{$host})) { print "no color for $host\n"; $noColorFound{$host} = 1; } $color = '00 00 00'; } return $color; } --- NEW FILE: query.pl --- #!/usr/bin/perl use strict; use Getopt::Std; use Frontier::Client; use Data::Dumper; my $PORT=55504; my $API_PORT=55501; my $USE_HEIGHT = 1; my $DEBUG = 0; my $usage = "query.pl [options] url\n"; $usage .= " -l: get local coordinate of node running at url\n"; $usage .= " -s subset.dat: file containing list of remote nodes, one per line\n"; $usage .= " -r remote-node: get remote overlay node coordinate\n"; $usage .= " -p proxy-node: get proxy coord that is stored on contacted node\n"; $usage .= " -a nodeA -b nodeB: estimate latency btw overlay nodes A and B\n"; $usage .= " -d debug\n"; $usage .= "\n"; $usage .= "query.pl -l http://righthand.eecs.harvard.edu\n"; $usage .= "query.pl -a sb02.eecs.harvard.edu -b sb03.eecs.harvard.edu http://sb01.eecs.harvard.edu\n"; $usage .= "Default port numbers can be overridden with \":port\" syntax\n"; my %para = (); getopts('lr:a:b:s:d', \%para); ############################################################ if (defined($para{'d'})) { $DEBUG = 1; } if ($#ARGV < 0) { die ("Missing arguments\n$usage"); } my $url = $ARGV[0]; if ($url !~ /^http:\/\//) { $url = 'http://'.$url; } if ($url =~ /^http:\/\/[\w+\.-]+$/) { $url .= ":$API_PORT/xmlrpc" } if ($url =~ /^http:\/\/[\w+\.-]+:\d+$/) { $url .= "/xmlrpc"; } if ($url !~ /^http:\/\/[\w+\.-]+:\d+\/xmlrpc$/) { die ("word: $url\n$usage\n"); } ############################################################ #warn "url $url\n"; my $server = Frontier::Client->new(url => "$url", debug => $DEBUG); if (defined($para{'l'})) { my $coordArray = $server->call("pyxida.getLocalCoord"); if ($DEBUG) { print Dumper($coordArray); } my $coord = &parse_coord ($coordArray); print "$coord\n"; } elsif (defined($para{'s'})) { my %remoteNodes = (); open IN, "$para{'s'}" or die ("Cannot open file $para{'s'}\n"); while (my $line = <IN>) { $line =~ s/\s//g; next if ($line =~ /\#/); if ($line =~ /\w+/) { my $node = &addPort ($line,$PORT); $remoteNodes{$node} = 1; } } close IN; my $node2coord = $server->call("pyxida.getRemoteCoords", \%remoteNodes); if ($DEBUG) { print Dumper($node2coord); } foreach my $node (keys %$node2coord) { my $coordArray = $node2coord->{$node}; if ($node ne 'result') { my $coord = &parse_coord ($coordArray); print "$node $coord\n"; } } if ((defined($node2coord->{'result'})) && ($node2coord->{'result'} ne 'Success')) { warn "$node2coord->{'result'}\n"; } } elsif (defined($para{'r'})) { my $remoteNode = &addPort ($para{'r'},$PORT); my $resHash = $server->call("pyxida.getRemoteCoord", $remoteNode); if ($DEBUG) { print Dumper($resHash); } if (defined($resHash->{'result'})) { if (($resHash->{'result'} eq 'Success') && (defined($resHash->{'coord'}))) { my $coord = &parse_coord ($resHash->{'coord'}); print "$coord\n"; } else { warn "Failure: $resHash->{'result'}\n"; } } else { warn "Failure: cause unknown\n"; } } elsif (defined($para{'a'}) && defined($para{'b'})) { my $nodeA = &addPort($para{'a'},$PORT); my $nodeB = &addPort($para{'b'},$PORT); my $distance = $server->call("pyxida.estimateRTT", $nodeA, $nodeB); if ($DEBUG) { print Dumper($distance); } if (defined($distance)) { $distance = sprintf ("%.3f", $distance); print "$distance\n"; } } else { die ("Missing arguments\n$usage"); } sub parse_coord { my ($coord) = @_; my $out = '['; for (my $i = 0; $i <= $#$coord; $i++) { my $element = sprintf ("%.3f", $coord->[$i]); if ($i == $#$coord && $USE_HEIGHT) { $out .= 'h'; } $out .= $element; if ($i != $#$coord) { $out .= ' '; } } $out .= ']'; return $out; } sub addPort { my ($host,$port) = @_; if ($host !~ /[\w]+:\d+/) { $host .= ":$port"; } return $host; } |