lib/PublicInbox/Mbox.pm | 11 ++--------- lib/PublicInbox/Msgmap.pm | 19 ++++++++----------- lib/PublicInbox/NNTP.pm | 12 ++++-------- t/nntpd.t | 1 + t/v2writable.t | 7 +++++++ diff --git a/lib/PublicInbox/Mbox.pm b/lib/PublicInbox/Mbox.pm index 0be1968584d9c68a7a76a72b98f82afea13bc564..c66ccaa794fd1f5413a545b09bcd3cc5db22944f 100644 --- a/lib/PublicInbox/Mbox.pm +++ b/lib/PublicInbox/Mbox.pm @@ -166,14 +166,7 @@ eval { require IO::Compress::Gzip }; return sub { need_gzip(@_) } if $@; if ($query eq '') { my $prev = 0; - my $msgs = []; - my $cb = sub { - $ctx->{-inbox}->mm->id_batch($prev, sub { - $msgs = $_[0]; - }); - $prev = $msgs->[-1] if @$msgs; - $msgs; - }; + my $cb = sub { $ctx->{-inbox}->mm->ids_after(\$prev) }; return PublicInbox::MboxGz->response($ctx, $cb, 'all'); } my $opts = { offset => 0 }; @@ -244,7 +237,7 @@ my $msgs = $self->{msgs}; do { # work on existing result set while (defined(my $smsg = shift @$msgs)) { - # id_batch may return integers + # ids_after may return integers ref($smsg) or $smsg = $ctx->{srch}->{over_ro}->get_art($smsg); diff --git a/lib/PublicInbox/Msgmap.pm b/lib/PublicInbox/Msgmap.pm index dea957316609ffb63332098d0e994945447ca4bd..26565d456b6c5d4b5d0ce320297dcb8e4ee5d7e2 100644 --- a/lib/PublicInbox/Msgmap.pm +++ b/lib/PublicInbox/Msgmap.pm @@ -186,17 +186,14 @@ 'val VARCHAR(255) NOT NULL)'); } # used by NNTP.pm -sub id_batch { - my ($self, $num, $cb) = @_; - my $dbh = $self->{dbh}; - my $sth = $dbh->prepare('SELECT num FROM msgmap WHERE num > ? '. - 'ORDER BY num ASC LIMIT 1000'); - $sth->execute($num); - my $ary = $sth->fetchall_arrayref; - @$ary = map { $_->[0] } @$ary; - my $nr = scalar @$ary; - $cb->($ary) if $nr; - $nr; +sub ids_after { + my ($self, $num) = @_; + my $ids = $self->{dbh}->selectcol_arrayref(<<'', undef, $$num); +SELECT num FROM msgmap WHERE num > ? +ORDER BY num ASC LIMIT 1000 + + $$num = $ids->[-1] if @$ids; + $ids; } # only used for mapping external serial numbers (e.g. articles from gmane) diff --git a/lib/PublicInbox/NNTP.pm b/lib/PublicInbox/NNTP.pm index ff6d89587756fa70bd8708f5a1c716a91b6d11f7..b91cda1d175a3bfc2790d1aabdbcb66f5afa3bef 100644 --- a/lib/PublicInbox/NNTP.pm +++ b/lib/PublicInbox/NNTP.pm @@ -34,7 +34,6 @@ my $LIST_HEADERS = join("\r\n", @OVERVIEW, qw(:bytes :lines Xref To Cc)) . "\r\n"; # disable commands with easy DoS potential: -# LISTGROUP could get pretty bad, too... my %DISABLED; # = map { $_ => 1 } qw(xover list_overview_fmt newnews xhdr); my $EXPMAP; # fd -> [ idle_time, $self ] @@ -225,15 +224,12 @@ more($self, $res); } $self->{ng} or return '412 no newsgroup selected'; + my $n = 0; long_response($self, 0, long_response_limit, sub { my ($i) = @_; - my $nr = $self->{ng}->mm->id_batch($$i, sub { - my ($ary) = @_; - more($self, join("\r\n", @$ary)); - }); - - # -1 to adjust for implicit increment in long_response - $$i = $nr ? $$i + $nr - 1 : long_response_limit; + my $ary = $self->{ng}->mm->ids_after(\$n); + scalar @$ary or return ($$i = long_response_limit); + more($self, join("\r\n", @$ary)); }); } diff --git a/t/nntpd.t b/t/nntpd.t index de781d74b3b85bc88ab193865200dc78ba3982a9..c6e34ed3967ae00f79058d9d714cf41741d2eac7 100644 --- a/t/nntpd.t +++ b/t/nntpd.t @@ -123,6 +123,7 @@ my $n = Net::NNTP->new($host_port); my $list = $n->list; is_deeply($list, { $group => [ qw(1 1 n) ] }, 'LIST works'); is_deeply([$n->group($group)], [ qw(0 1 1), $group ], 'GROUP works'); + is_deeply($n->listgroup($group), [1], 'listgroup OK'); %opts = ( PeerAddr => $host_port, diff --git a/t/v2writable.t b/t/v2writable.t index 1e8e40426138bc286bdd7a48f7fe089013d69d79..629473516bfaeaa6f266c7fd94874b959caa4878 100644 --- a/t/v2writable.t +++ b/t/v2writable.t @@ -189,6 +189,13 @@ foreach my $mid (@{$n->newnews(0, $group)}) { is($nn{$mid}++, 0, "MID is unique in NEWNEWS"); } is_deeply([sort keys %nn], [sort keys %uniq]); + + my %lg; + foreach my $num (@{$n->listgroup($group)}) { + is($lg{$num}++, 0, "num is unique in LISTGROUP"); + } + is_deeply([sort keys %lg], [sort keys %$x], + 'XOVER and LISTGROUPS return the same article numbers'); }; { local $ENV{NPROC} = 2;