X-Git-Url: http://git.indexdata.com/?p=irspy-moved-to-github.git;a=blobdiff_plain;f=lib%2FZOOM%2FIRSpy.pm;h=b3c0aeb15e8de464b155625bccabe60bd052d75d;hp=fa7606a41b5463fa16c69f54edad49363a199af7;hb=09a78b8e8d348d62681278705447c19070cbd6b1;hpb=5c949cbd4b445a767298bec4b3465a5dded1f3a1 diff --git a/lib/ZOOM/IRSpy.pm b/lib/ZOOM/IRSpy.pm index fa7606a..b3c0aeb 100644 --- a/lib/ZOOM/IRSpy.pm +++ b/lib/ZOOM/IRSpy.pm @@ -1,4 +1,4 @@ -# $Id: IRSpy.pm,v 1.61 2007-02-21 17:57:59 mike Exp $ +# $Id: IRSpy.pm,v 1.72 2007-02-28 17:36:00 mike Exp $ package ZOOM::IRSpy; @@ -132,6 +132,15 @@ sub targets { } +sub find_targets { + my $this = shift(); + my($query) = @_; + + $this->{allrecords} = 0; + $this->{query} = $query; +} + + # Also used by ZOOM::IRSpy::Record sub _parse_target_string { my($target) = @_; @@ -179,7 +188,7 @@ sub initialise { # access point -- not even 1035 "everywhere" -- so instead we # hack together a search that we know will find all records. $this->{query} = "port=?*"; - } else { + } elsif ($this->{targets}) { # Prepopulate the target map with nulls so that after we fill # in what we can from the database query, we know which target # IDs we need new records for. @@ -190,8 +199,10 @@ sub initialise { $this->log("irspy_debug", "query '", $this->{query}, "'"); my $rs = $this->{conn}->search(new ZOOM::Query::CQL($this->{query})); + $this->log("irspy", "'", $this->{query}, "' found ", + $rs->size(), " target records"); delete $this->{query}; # No longer needed at all - $this->log("irspy_debug", "found ", $rs->size(), " target records"); + my $gatherTargets = !$this->{targets}; foreach my $i (1 .. $rs->size()) { my $target = _render_record($rs, $i-1, "id"); my $zeerex = _render_record($rs, $i-1, "zeerex"); @@ -199,7 +210,7 @@ sub initialise { $target2record{lc($target)} = new ZOOM::IRSpy::Record($this, $target, $zeerex); push @{ $this->{targets} }, $target - if $this->{allrecords}; + if $gatherTargets; } # Make records for targets not previously in the database @@ -252,7 +263,8 @@ sub _irspy_to_zeerex { if ($save_xml) { unlink('/tmp/irspy_orig.xml'); - open FH, '>/tmp/irspy_orig.xml'; + open FH, '>/tmp/irspy_orig.xml' + or die "can't write irspy_orig.xml: $!"; print FH $irspy_doc->toString(); close FH; } @@ -260,7 +272,8 @@ sub _irspy_to_zeerex { my $result = $this->{irspy_to_zeerex_style}->transform($irspy_doc, %params); if ($save_xml) { unlink('/tmp/irspy_transformed.xml'); - open FH, '>/tmp/irspy_transformed.xml'; + open FH, '>/tmp/irspy_transformed.xml' + or die "can't write irspy_transformed.xml: $!"; print FH $result->toString(); close FH; } @@ -336,6 +349,7 @@ sub check { $tname = "Main" if !defined $tname; $this->{tree} = $this->_gather_tests($tname) or die "No tests defined for '$tname'"; + $this->{tree}->resolve(); #$this->{tree}->print(0); my $nskipped = 0; @@ -364,6 +378,7 @@ sub check { } if (!defined $nextaddr) { $conn->log("irspy", "has no more tests: removing"); + ### Does this go wrong if two connections are exhausted? splice @conn, $i0, 1; $this->_rewrite_record($conn); $conn->option(rewrote_record => 1); @@ -397,46 +412,42 @@ sub check { $conn->current_task($task); $task->run(); } - - # Do we need to test $conn->is_idle()? I don't think so! } + NEXT_EVENT: my $i0 = ZOOM::event(\@conn); $this->log("irspy_event", "ZOOM_event(", scalar(@conn), " connections) = $i0"); - if ($i0 == -3 || $i0 == 0) { - # no connections left, or no events on those that remain - $this->log("irspy", "no events remain"); + if ($i0 < 1) { + my %messages = ( + 0 => "no events remain", + -1 => "ZOOM::event() argument not a reference", + -2 => "ZOOM::event() reference not an array", + -3 => "no connections remain", + -4 => "too many connections for ZOOM::event()", + ); + my $message = $messages{$i0} || "ZOOM::event() returned $i0"; + $this->log("irspy", $message); last; } + my $conn = $conn[$i0-1]; my $ev = $conn->last_event(); my $evstr = ZOOM::event_str($ev); $conn->log("irspy_event", "event $ev ($evstr)"); + goto NEXT_EVENT if $ev != ZOOM::Event::ZEND; my $task = $conn->current_task(); die "$conn has no current task for event $ev ($evstr)" if !$task; - eval { $conn->_check() }; - if ($@ && - ($ev == ZOOM::Event::RECV_DATA || - $ev == ZOOM::Event::ZEND)) { - # An error in, say, a search response, becomes visible to - # ZOOM before the Receive Data event is sent and persists - # until after the End, which means that successive events - # each report the same error. So we just ignore errors on - # "unimportant" events. ### But this doesn't work for, - # say, a Connection Refused, as the only event that shows - # us this error is the ZEND. - $conn->log("irspy_event", "ignoring error ", - "on event $ev ($evstr): $@"); - next; - } my $res; - if ($@) { + eval { $conn->check() }; + if ($@ && ref $@ && $@->isa("ZOOM::Exception")) { my $sub = $task->{cb}->{exception}; die $@ if !defined $sub; $res = &$sub($conn, $task, $task->udata(), $@); + } elsif ($@) { + die "Unexpected non-ZOOM exception: " . ref($@) . " ($@)"; } else { my $sub = $task->{cb}->{$ev}; if (!defined $sub) { @@ -467,19 +478,29 @@ sub check { $conn->next_task(0); if ($res == ZOOM::IRSpy::Status::TEST_BAD) { my $address = $conn->option('current_test_address'); - ($address, my $n) = $this->_last_sibling_test($address); - if (defined $address) { - $conn->log("irspy_test", "skipped $n tests"); - $conn->option(current_test_address => $address); - $nskipped += $n; + $conn->log("irspy", "top-level test failed!") + if $address eq ""; + my $node = $this->{tree}->select($address); + my $skipcount = 0; + while (defined $node->next() && + length($node->next()->address()) >= length($address)) { + $conn->log("irspy_debug", "skipping from '", + $node->address(), "' to '", + $node->next()->address(), "'"); + $node = $node->next(); + $skipcount++; } + + $conn->option(current_test_address => $node->address()); + $conn->log("irspy_test", "skipped $skipcount tests"); + $nskipped += $skipcount; } } elsif ($res == ZOOM::IRSpy::Status::TEST_SKIPPED) { $conn->log("irspy_test", "test skipped during task $task"); $conn->current_task(0); $conn->next_task(0); - # I think that's all we need to do + $nskipped++; } else { die "unknown callback return-value '$res'"; @@ -489,11 +510,13 @@ sub check { $this->log("irspy", "exiting main loop"); # Sanity checks: none of the following should ever happen my $finished = 1; - foreach my $conn (@{ $this->{connections} }) { + @conn = @{ $this->{connections} }; + foreach my $conn (@conn) { my $test = $conn->option("current_test_address"); my $next = $this->_next_test($test); if (defined $next) { - $this->log("irspy", "$conn (in test '$test') has queued test '$next'"); + $this->log("irspy", + "$conn (in test '$test') has queued test '$next'"); $finished = 0; } if (my $task = $conn->current_task()) { @@ -505,7 +528,8 @@ sub check { $finished = 0; } if (!$conn->is_idle()) { - $this->log("irspy", "$conn still has ZOOM-C level tasks queued: see below"); + $this->log("irspy", + "$conn still has ZOOM-C level tasks queued: see below"); $finished = 0; } my $ev = $conn->peek_event(); @@ -521,9 +545,10 @@ sub check { } # This really shouldn't be necessary, and in practice it rarely - # helps, but it's belt and braces + # helps, but it's belt and braces. (For now, we don't do this + # hence the zero in the $nruns check). if (!$finished) { - if (++$nruns < 3) { + if (++$nruns < 0) { $this->log("irspy", "back into main loop, ${nruns}th time"); goto ROUND_AND_ROUND_WE_GO; } else { @@ -532,12 +557,12 @@ sub check { } # This shouldn't happen emit anything either: - @conn = @{ $this->{connections} }; - while (my $i1 = ZOOM::event(\@conn)) { + while ((my $i1 = ZOOM::event(\@conn)) > 0) { my $conn = $conn[$i1-1]; my $ev = $conn->last_event(); my $evstr = ZOOM::event_str($ev); - warn "$conn still has ZOOM-C level task queued: $ev ($evstr)" + $this->log("irspy", + "$conn still has ZOOM-C level task queued: $ev ($evstr)") if $ev != ZOOM::Event::ZEND; }