X-Git-Url: http://www.dxcluster.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=perl%2FDXXml%2FPing.pm;h=a1b0a6a122ba6e3a8a792ef69d819c4216b9ecb0;hb=7ed0b26aa8f65327d111e16b176316e823000e9d;hp=26dd864e26e3c3429d29ca8241ed42b78021569f;hpb=90eb20e9a8dbeb041cc2f77fbea05849bdc09245;p=spider.git diff --git a/perl/DXXml/Ping.pm b/perl/DXXml/Ping.pm index 26dd864e..a1b0a6a1 100644 --- a/perl/DXXml/Ping.pm +++ b/perl/DXXml/Ping.pm @@ -13,14 +13,17 @@ package DXXml::Ping; use DXDebug; use DXProt; use IsoTime; +use Investigate; +use Time::HiRes qw(gettimeofday tv_interval); -use vars qw($VERSION $BRANCH @ISA); +use vars qw($VERSION $BRANCH @ISA %pings); $VERSION = sprintf( "%d.%03d", q$Revision$ =~ /(\d+)\.(\d+)/ ); $BRANCH = sprintf( "%d.%03d", q$Revision$ =~ /\d+\.\d+\.(\d+)\.(\d+)/ || (0,0)); $main::build += $VERSION; $main::branch += $BRANCH; @ISA = qw(DXXml); +%pings = (); # outstanding ping requests outbound sub handle_input { @@ -29,4 +32,91 @@ sub handle_input } +sub topcxx +{ + my $self = shift; + unless (exists $self->{'-pcxx'}) { + $self->{'-pcxx'} = DXProt::pc51($self->{to}, $self->{o}, $self->{s}); + } + return $self->{'-pcxx'}; +} + +# add a ping request to the ping queues +sub add +{ + my ($dxchan, $to, $via) = @_; + my $from = $dxchan->call; + my $ref = $pings{$to} || []; + my $r = {}; + my $self = DXXml::Ping->new(to=>$to, '-hirestime'=>[ gettimeofday ], s=>'1'); + $self->{u} = $from unless $from eq $main::mycall; + $self->{'-via'} = $via if $via && DXChannel::get($via); + $self->{o} = $main::mycall; + $self->{id} = $self->nextid; + $self->route($dxchan); + + push @$ref, $self; + $pings{$to} = $ref; + my $u = DXUser->get_current($to); + if ($u) { + $u->lastping(($via || $from), $main::systime); + $u->put; + } +} + +sub handle_ping_reply +{ + my $fromdxchan = shift; + my $from = shift; + my $fromxml; + + if (ref $from) { + $fromxml = $from; + $from = $from->{o}; + } + + # it's a reply, look in the ping list for this one + my $ref = $pings{$from}; + return unless $ref; + + my $tochan = DXChannel::get($from); + while (@$ref) { + my $r = shift @$ref; + my $dxchan = DXChannel::get($r->{to}); + next unless $dxchan; + my $t = tv_interval($r->{'-hirestime'}, [ gettimeofday ]); + if ($dxchan->is_user) { + my $s = sprintf "%.2f", $t; + my $ave = sprintf "%.2f", $tochan ? ($tochan->{pingave} || $t) : $t; + $dxchan->send($dxchan->msg('pingi', $from, $s, $ave)) + } elsif ($dxchan->is_node) { + if ($tochan) { + my $nopings = $tochan->user->nopings || $DXProt::obscount; + push @{$tochan->{pingtime}}, $t; + shift @{$tochan->{pingtime}} if @{$tochan->{pingtime}} > 6; + + # cope with a missed ping, this means you must set the pingint large enough + if ($t > $tochan->{pingint} && $t < 2 * $tochan->{pingint} ) { + $t -= $tochan->{pingint}; + } + + # calc smoothed RTT a la TCP + if (@{$tochan->{pingtime}} == 1) { + $tochan->{pingave} = $t; + } else { + $tochan->{pingave} = $tochan->{pingave} + (($t - $tochan->{pingave}) / 6); + } + $tochan->{nopings} = $nopings; # pump up the timer + if (my $ivp = Investigate::get($from, $fromdxchan->{call})) { + $ivp->handle_ping; + } + } elsif (my $rref = Route::Node::get($r->{to})) { + if (my $ivp = Investigate::get($from, $fromdxchan->{to})) { + $ivp->handle_ping; + } + } + } + } +} + 1;