X-Git-Url: http://git.indexdata.com/?a=blobdiff_plain;f=lib%2FZOOM%2FIRSpy.pm;h=a496c67e78bf2115dc3e4fb63142d2fa953ec0ba;hb=9a2899855f877172facc65a396ce5f6157d3ecd3;hp=e6f2c52eb6ac82ead454618866b23b2cf770da89;hpb=b85c3066c7c964a9fdc452ed34df1ece186c43fe;p=irspy-moved-to-github.git diff --git a/lib/ZOOM/IRSpy.pm b/lib/ZOOM/IRSpy.pm index e6f2c52..a496c67 100644 --- a/lib/ZOOM/IRSpy.pm +++ b/lib/ZOOM/IRSpy.pm @@ -1,4 +1,4 @@ -# $Id: IRSpy.pm,v 1.48 2006-11-03 13:11:29 mike Exp $ +# $Id: IRSpy.pm,v 1.66 2007-02-23 13:18:43 mike Exp $ package ZOOM::IRSpy; @@ -16,7 +16,8 @@ use Net::Z3950::ZOOM 1.13; # For the ZOOM version-check only use ZOOM::IRSpy::Node; use ZOOM::IRSpy::Connection; use ZOOM::IRSpy::Record; -use ZOOM::IRSpy::Utils; +use ZOOM::IRSpy::Stats; +use ZOOM::IRSpy::Utils qw(cql_target); our @ISA = qw(); our $VERSION = '0.02'; @@ -41,7 +42,9 @@ ZOOM::IRSpy - Perl extension for discovering and analysing IR services use ZOOM::IRSpy; $spy = new ZOOM::IRSpy("target/string/for/irspy/database"); - print $spy->report_status(); + $spy->targets(@targets); + $spy->initialise(); + $res = $spy->check("Main"); =head1 DESCRIPTION @@ -72,6 +75,10 @@ sub new { or die "$0: can't connection to IRSpy database 'dbname'"; my $xslt = new XML::LibXSLT; + + $xslt->register_function($ZOOM::IRSpy::Utils::IRSPY_NS, 'strcmp', + \&ZOOM::IRSpy::Utils::xslt_strcmp); + my $libxml = new XML::LibXML; my $xsl_doc = $libxml->parse_file($irspy_to_zeerex_xsl); my $irspy_to_zeerex_style = $xslt->parse_stylesheet($xsl_doc); @@ -117,7 +124,7 @@ sub targets { $this->log("irspy_debug", "rewriting '$target' to '$newtarget'"); $target = $newtarget; # This is written through the ref } - push @qlist, (qq[(host="$host" and port="$port" and path="$db")]); + push @qlist, cql_target($host, $port, $db); } $this->{targets} = \@targets; @@ -239,10 +246,24 @@ sub _render_record { sub _irspy_to_zeerex { - my ($this, $conn) = @_; + my $this = shift(); + my($conn, $save_xml) = @_; my $irspy_doc = $conn->record()->{zeerex}->ownerDocument; + + if ($save_xml) { + unlink('/tmp/irspy_orig.xml'); + open FH, '>/tmp/irspy_orig.xml'; + print FH $irspy_doc->toString(); + close FH; + } my %params = (); 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'; + print FH $result->toString(); + close FH; + } return $result->documentElement(); } @@ -253,7 +274,7 @@ sub _rewrite_record { my($conn) = @_; $conn->log("irspy", "rewriting XML record"); - my $rec = $this->_irspy_to_zeerex($conn); + my $rec = $this->_irspy_to_zeerex($conn, $ENV{IRSPY_SAVE_XML}); _really_rewrite_record($this->{conn}, $rec); } @@ -320,6 +341,8 @@ sub check { my @conn = @{ $this->{connections} }; + my $nruns = 0; + ROUND_AND_ROUND_WE_GO: while (1) { my @copy_conn = @conn; # avoid alias problems after splice() my $nconn = scalar(@copy_conn); @@ -341,6 +364,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); @@ -374,14 +398,24 @@ sub check { $conn->current_task($task); $task->run(); } - - # Do we need to test $conn->is_idle()? I don't think so! } my $i0 = ZOOM::event(\@conn); $this->log("irspy_event", "ZOOM_event(", scalar(@conn), " connections) = $i0"); - last if $i0 == 0 || $i0 == -3; # no events or no connections + 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); @@ -392,15 +426,19 @@ sub check { eval { $conn->_check() }; if ($@ && ($ev == ZOOM::Event::RECV_DATA || - $ev == ZOOM::Event::RECV_APDU || - $ev == ZOOM::Event::ZEND)) { + $ev == ZOOM::Event::ZEND || + ($ev == ZOOM::Event::RECV_APDU && + !$task->isa("ZOOM::IRSpy::Task::Connect")))) { # 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 End. + # "unimportant" events. We can also ignore errors on + # RECV_APDU in most cases, but since there is no RECV_INIT + # event, we need to avoid doing this if the task is + # Connect. Yuck -- special cases. + # ### 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; @@ -450,7 +488,7 @@ sub check { } } elsif ($res == ZOOM::IRSpy::Status::TEST_SKIPPED) { - $conn->log("irspy_task", "test skipped during task $task"); + $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 @@ -462,26 +500,63 @@ sub check { $this->log("irspy", "exiting main loop"); # Sanity checks: none of the following should ever happen - foreach my $conn (@{ $this->{connections} }) { + my $finished = 1; + @conn = @{ $this->{connections} }; + foreach my $conn (@conn) { my $test = $conn->option("current_test_address"); my $next = $this->_next_test($test); if (defined $next) { - warn "$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()) { - warn "$conn still has an active task $task"; + $this->log("irspy", "$conn still has an active task $task"); + $finished = 0; } if (my $task = $conn->next_task()) { - warn "$conn still has a queued task $task"; + $this->log("irspy", "$conn still has a queued task $task"); + $finished = 0; } if (!$conn->is_idle()) { - warn "$conn is not idle (still has ZOOM-C level tasks queued)"; + $this->log("irspy", + "$conn still has ZOOM-C level tasks queued: see below"); + $finished = 0; + } + my $ev = $conn->peek_event(); + if ($ev != 0 && $ev != ZOOM::Event::ZEND) { + my $evstr = ZOOM::event_str($ev); + $this->log("irspy", "$conn has event $ev ($evstr) waiting"); + $finished = 0; } if (!$conn->option("rewrote_record")) { - warn "$conn did not rewrite its ZeeRex record"; + $this->log("irspy", "$conn did not rewrite its ZeeRex record"); + $finished = 0; } } + # This really shouldn't be necessary, and in practice it rarely + # 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 < 0) { + $this->log("irspy", "back into main loop, ${nruns}th time"); + goto ROUND_AND_ROUND_WE_GO; + } else { + $this->log("irspy", "bailing after $nruns main-loop runs"); + } + } + + # This shouldn't happen emit anything either: + while ((my $i1 = ZOOM::event(\@conn)) > 0) { + my $conn = $conn[$i1-1]; + my $ev = $conn->last_event(); + my $evstr = ZOOM::event_str($ev); + $this->log("irspy", + "$conn still has ZOOM-C level task queued: $ev ($evstr)") + if $ev != ZOOM::Event::ZEND; + } + return $nskipped; } @@ -556,8 +631,8 @@ sub _last_sibling_test { my $maybe = $this->_next_sibling_test($address); last if !defined $maybe; $nskipped++; - $this->log("irspy", "skipping $nskipped tests to '$address'"); $address = $maybe; + $this->log("irspy", "skipping $nskipped tests to '$address'"); } return ($address, $nskipped);