# Copyright (C) all contributors
# License: AGPL-3.0+
# mocks Xapian::Mset and allows slow queries from blocking the event loop
package PublicInbox::XhcMset;
use v5.12;
use parent qw(PublicInbox::DS);
use PublicInbox::XhcMsetIterator;
use PublicInbox::Syscall qw(EPOLLIN EPOLLONESHOT);
sub event_step {
my ($self) = @_;
my ($cb, @args) = @{delete $self->{cb_args} // return};
my $rd = $self->{sock};
eval {
my $hdr = <$rd> // die "E: reading mset header: $!";
for (split /\s+/, $hdr) { # read mset.size + estimated_matches
my ($k, $v) = split /=/, $_, 2;
$k =~ s/\A[^\.]*\.//; # s/(mset)?\./
$self->{$k} = $v;
}
my $size = $self->{size} // die "E: bad xhc header: `$hdr'";
my @it = map { PublicInbox::XhcMsetIterator::make($_) } <$rd>;
$self->{items} = \@it;
scalar(@it) == $size or die
'E: got ',scalar(@it),", expected mset.size=$size";
};
my $err = $@;
$self->close;
eval { $cb->(@args, $self, $err) };
warn "E: $@\n" if $@;
}
sub maybe_new {
my (undef, $rd, $srch, @cb_args) = @_;
my $self = bless { cb_args => \@cb_args, srch => $srch }, __PACKAGE__;
if ($PublicInbox::DS::in_loop) { # async
$self->SUPER::new($rd, EPOLLIN|EPOLLONESHOT);
} else { # synchronous
$self->{sock} = $rd;
event_step($self);
undef;
}
}
eval(join('', map { "sub $_ { \$_[0]->{$_} }\n" } qw(size
get_matches_estimated)));
sub items { @{$_[0]->{items}} }
1;