X-Git-Url: http://www.git.stargrave.org/?a=blobdiff_plain;f=lib%2FPublicInbox%2FNNTP.pm;h=5c5df7b0dcbe548c0284504c84ec64f782de8d18;hb=fe86054ee1e2d93b19762a34ed1aaebe43635ff0;hp=cdbd8e98c08b8ef95ebe57e89d9a2ffe0b12ceb0;hpb=cfb8d16578e7f2f2e300f9f436205e4a8fc7f322;p=public-inbox.git diff --git a/lib/PublicInbox/NNTP.pm b/lib/PublicInbox/NNTP.pm index cdbd8e98..5c5df7b0 100644 --- a/lib/PublicInbox/NNTP.pm +++ b/lib/PublicInbox/NNTP.pm @@ -5,7 +5,7 @@ package PublicInbox::NNTP; use strict; use warnings; -use base qw(Danga::Socket); +use base qw(PublicInbox::DS); use fields qw(nntpd article rbuf ng long_res); use PublicInbox::Search; use PublicInbox::Msgmap; @@ -23,12 +23,11 @@ use constant { r224 => '224 Overview information follows (multi-line)', r225 => '225 Headers follow (multi-line)', r430 => '430 No article with that message-id', - long_response_limit => 0xffffffff, }; sub now () { clock_gettime(CLOCK_MONOTONIC) }; -my @OVERVIEW = qw(Subject From Date Message-ID References); +my @OVERVIEW = qw(Subject From Date Message-ID References Xref); my $OVERVIEW_FMT = join(":\r\n", @OVERVIEW, qw(Bytes Lines)) . ":\r\n"; my $LIST_HEADERS = join("\r\n", @OVERVIEW, qw(:bytes :lines Xref To Cc)) . "\r\n"; @@ -51,8 +50,16 @@ sub next_tick () { # before finishing reading: if (my $long_cb = $nntp->{long_res}) { $nntp->write($long_cb); - } elsif (&Danga::Socket::POLLIN & $nntp->{event_watch}) { + } else { + # pipelined request, we bypassed socket-readiness + # checks to get here: event_read($nntp); + + # maybe there's more pipelined data, or we'll have + # to register it for socket-readiness notifications + if (!$nntp->{long_res} && !$nntp->{closed}) { + check_read($nntp); + } } } } @@ -94,7 +101,7 @@ sub new ($$$) { my $self = fields::new($class); $self->SUPER::new($sock); $self->{nntpd} = $nntpd; - res($self, '201 server ready - post via email'); + res($self, '201 ' . $nntpd->{servername} . ' ready - post via email'); $self->{rbuf} = ''; $self->watch_read(1); update_idle_time($self); @@ -115,7 +122,7 @@ sub args_ok ($$) { sub process_line ($$) { my ($self, $l) = @_; my ($req, @args) = split(/\s+/, $l); - return unless defined($req); + return 1 unless defined($req); # skip blank line $req = lc($req); $req = eval { no strict 'refs'; @@ -410,7 +417,7 @@ sub header_append ($$$) { sub xref ($$$$) { my ($self, $ng, $n, $mid) = @_; - my $ret = "$ng->{domain} $ng->{newsgroup}:$n"; + my $ret = $self->{nntpd}->{servername} . " $ng->{newsgroup}:$n"; # num_for is pretty cheap and sometimes we'll lookup the existence # of an article without getting even the OVER info. In other words, @@ -507,6 +514,7 @@ sub set_art { sub _header ($) { my $hdr = $_[0]->header_obj->as_string; utf8::encode($hdr); + $hdr =~ s/(?watch_read(1); + check_read($self); } } elsif ($more) { # $self->{write_buf_size}: # no recursion, schedule another call ASAP @@ -620,7 +628,7 @@ sub long_response ($$) { $nextt ||= PublicInbox::EvCleanup::asap(*next_tick); } else { # all done! $self->{long_res} = undef; - $self->watch_read(1); + check_read($self); res($self, '.'); out($self, " deferred[$fd] done - %0.6f", now() - $t0); } @@ -812,8 +820,8 @@ sub cmd_xrover ($;$) { }); } -sub over_line ($$) { - my ($num, $smsg) = @_; +sub over_line ($$$$) { + my ($self, $ng, $num, $smsg) = @_; # n.b. field access and procedural calls can be # 10%-15% faster than OO method calls: my $s = join("\t", $num, @@ -823,7 +831,8 @@ sub over_line ($$) { "<$smsg->{mid}>", $smsg->{references}, $smsg->{bytes}, - $smsg->{lines}); + $smsg->{lines}, + "Xref: " . xref($self, $ng, $num, $smsg->{mid})); utf8::encode($s); $s } @@ -839,7 +848,7 @@ sub cmd_over ($;$) { # Only set article number column if it's the current group my $self_ng = $self->{ng}; $n = 0 if (!$self_ng || $self_ng ne $ng); - more($self, over_line($n, $smsg)); + more($self, over_line($self, $ng, $n, $smsg)); '.'; } else { cmd_xover($self, $range); @@ -861,7 +870,7 @@ sub cmd_xover ($;$) { # OVERVIEW.FMT more($self, join("\r\n", map { - over_line($_->{num}, $_); + over_line($self, $self->{ng}, $_->{num}, $_); } @$msgs)); $cur = $msgs->[-1]->{num} + 1; }); @@ -893,7 +902,7 @@ sub more ($$) { sub do_write ($$) { my ($self, $data) = @_; my $done = $self->write($data); - return if $self->{closed}; + return 0 if $self->{closed}; # Do not watch for readability if we have data in the queue, # instead re-enable watching for readability when we can @@ -927,7 +936,7 @@ sub do_more ($$) { do_write($self, $data); } -# callbacks for Danga::Socket +# callbacks for PublicInbox::DS sub event_hup { $_[0]->close } sub event_err { $_[0]->close } @@ -967,10 +976,9 @@ sub event_read { update_idle_time($self); } -sub watch_read { - my ($self, $bool) = @_; - my $rv = $self->SUPER::watch_read($bool); - if ($bool && index($self->{rbuf}, "\n") >= 0) { +sub check_read { + my ($self) = @_; + if (index($self->{rbuf}, "\n") >= 0) { # Force another read if there is a pipelined request. # We don't know if the socket has anything for us to read, # and we must double-check again by the time the timer fires @@ -978,8 +986,11 @@ sub watch_read { # another long response. push @$nextq, $self; $nextt ||= PublicInbox::EvCleanup::asap(*next_tick); + } else { + # no pipelined requests available, let the kernel know + # to wake us up if there's more + $self->watch_read(1); # PublicInbox::DS::watch_read } - $rv; } sub not_idle_long ($$) {