diff options
Diffstat (limited to 'qooxdoo/source/perl/Qooxdoo/Services/Mtr.pm')
-rw-r--r-- | qooxdoo/source/perl/Qooxdoo/Services/Mtr.pm | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/qooxdoo/source/perl/Qooxdoo/Services/Mtr.pm b/qooxdoo/source/perl/Qooxdoo/Services/Mtr.pm new file mode 100644 index 0000000..6aead46 --- /dev/null +++ b/qooxdoo/source/perl/Qooxdoo/Services/Mtr.pm @@ -0,0 +1,128 @@ +package Qooxdoo::Services::Mtr; +use strict; +use POSIX qw(setsid :sys_wait_h); +use Time::HiRes qw(usleep); + +sub GetAccessibility { + return "public"; +} + +sub launch { + my $error = shift; + $SIG{CHLD} = \&REAPER; + defined(my $pid = fork) or do { $error->set_error(101,"Can't fork: $!");return $error}; + if ($pid){ + open my $x, ">/tmp/mtr_session.$pid" or do { + $error->set_error(199,"Opening /tmp/mtr_session.$$: $!"); + return $error; + }; + close ($x); + return $pid; + } + chdir '/' or die "Can't chdir to /: $!"; + open STDOUT, ">>/tmp/mtr_session.$$" + or die "Can't write to /tmp/mtr_session.$$: $!"; + open STDIN, '/dev/null' or die "Can't read /dev/null: $!"; + setsid or die "Can't start a new session: $!"; + open STDERR, '>&STDOUT' or die "Can't dup stdout: $!"; + exec @_; +} + +sub get_number { + my $error = shift; + my $data = shift; + $data = 'Undefined' unless defined $data; + if ($data =~ /^(\d+)$/){ + return $1; + } + else { + $error->set_error(104,"Expected a number but got: $data"); + return $error; + } +} + +sub method_stop_mtr { + my $error = shift; + my $arg = shift; + my $handle = get_number($error,$arg); + return $handle if ref $handle; + my $data = "/tmp/mtr_session.".$handle; + if (-r $data){ + warn "Sending kill $handle"; + kill('KILL',$handle); + } +} + +sub method_run_mtr +{ + my $error = shift; + my $arg = shift; + my $handle = get_number($error,$arg->{handle}); + my $point = get_number($error,$arg->{point}); + if ($arg->{host}){ + my $delay = get_number($error,$arg->{delay}); + return $delay if ref $delay; + my $rounds = get_number($error,$arg->{rounds}); + return $rounds if ref $rounds; + $handle = launch ($error,"mtr","-4","--raw","--report-cycles=$rounds","--interval=$delay",$arg->{host}); + $point = 0; + } + return $point if ref $point; + return $handle if ref $handle; + my $data = "/tmp/mtr_session.".$handle; + if (open my $fh,$data){ + my $again; + my $size; + my $rounds = 0; + do { + $size = -s $fh; + # make sure we reap any zombi instances of mtr + # this is especially important when running with speedy of fastcgi + waitpid($handle,WNOHANG); + $again = kill(0, $handle); + usleep(1000*200) if $rounds; +# print STDERR "$again, $handle, $size, $point\n"; + $rounds ++; + } while ($again and $point >= $size); + if (seek $fh, $point,0){ + my @array; + while (<$fh>){ + if (not /^[a-z]\s/){ + waitpid($handle,WNOHANG); + if (/Name or service not known/){ + $error->set_error(108,"Unknown hostname."); + return $error; + } + else { + $error->set_error(107,"ERROR: $_. See $data for more information."); + return $error; + } + } + last unless /\n$/; # stop when we find an incomplete line + $point = tell($fh); + chomp; + my @line = split (/\s+/,$_); + push @array,\@line; + }; + close $fh; + unlink $data unless $again; + return { + handle=>$handle, + point=>$point, + output=>\@array, + again=> $again, + } + } + else { + $error->set_error(102,"Seeking in mtr output to $point: $!"); + return $error; + } + } + else { + $error->set_error(103,"Opening $data: $!"); + return $error; + } +} + +1; + |