about summary refs log tree commit homepage
path: root/lib/PublicInbox/XapClient.pm
diff options
context:
space:
mode:
authorEric Wong <e@80x24.org>2023-08-24 01:22:33 +0000
committerEric Wong <e@80x24.org>2023-08-24 07:47:51 +0000
commitb18ecb7707e83cb8cb38c3736aecd984999ca0a7 (patch)
tree0f159212810c98aa07d26b6f7f28f4b8dbc9b302 /lib/PublicInbox/XapClient.pm
parentcf96412eb8f193ebd334fae340b2d91b6b7f2afe (diff)
downloadpublic-inbox-b18ecb7707e83cb8cb38c3736aecd984999ca0a7.tar.gz
This allows us to perform the expensive "dump_ibx" operations in
native C++ code using the Xapian C++ library.  This provides the
majority of the speedup with the -cindex --associate switch.

Eventually this may be expanded to cover all uses of Xapian
within the project to ensure we have access to Xapian APIs which
aren't available in XS|SWIG bindings; and also for
ease-of-installation on systems which don't provide
pre-packaged Perl Xapian bindings (e.g. OpenBSD 7.3) but
do provide Xapian development libraries.

Most of the C++ code is still C, as I'm not remotely familiar
with C++ compared to C.  I suspect many users and potential
hackers being from git, Linux kernel, and glibc world are in the
same boat.
Diffstat (limited to 'lib/PublicInbox/XapClient.pm')
-rw-r--r--lib/PublicInbox/XapClient.pm50
1 files changed, 50 insertions, 0 deletions
diff --git a/lib/PublicInbox/XapClient.pm b/lib/PublicInbox/XapClient.pm
new file mode 100644
index 00000000..56e3c3b4
--- /dev/null
+++ b/lib/PublicInbox/XapClient.pm
@@ -0,0 +1,50 @@
+#!perl -w
+# Copyright (C) all contributors <meta@public-inbox.org>
+# License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
+
+# This talks to (XapHelperCxx.pm + xap_helper.h) or XapHelper.pm
+# and will eventually allow users with neither XS nor SWIG Perl
+# bindings to use Xapian as long as they have Xapian development
+# headers/libs and a C++ compiler
+package PublicInbox::XapClient;
+use v5.12;
+use PublicInbox::Spawn qw(spawn);
+use Socket qw(AF_UNIX SOCK_SEQPACKET MSG_EOR);
+use PublicInbox::IPC;
+
+sub mkreq {
+        my ($self, $ios, @arg) = @_;
+        my ($r, $w, $n);
+        if (!defined($ios->[0])) {
+                pipe($r, $w) or die "pipe: $!";
+                $ios->[0] = $w;
+        }
+        my @fds = map fileno($_), @$ios;
+        my $buf = join("\0", @arg, '');
+        $n = PublicInbox::IPC::send_cmd($self->{io}, \@fds, $buf, MSG_EOR) //
+                die "send_cmd: $!";
+        $n == length($buf) or die "send_cmd: $n != ".length($buf);
+        $r;
+}
+
+sub start_helper {
+        my @argv = @_;
+        socketpair(my $sock, my $in, AF_UNIX, SOCK_SEQPACKET, 0) or
+                die "socketpair: $!";
+        my $cls = ($ENV{PI_NO_CXX} ? undef : eval {
+                        require PublicInbox::XapHelperCxx;
+                        PublicInbox::XapHelperCxx::check_build();
+                        'PublicInbox::XapHelperCxx';
+                }) // do {
+                        require PublicInbox::XapHelper;
+                        'PublicInbox::XapHelper';
+                };
+        # ensure the child process has the same @INC we do:
+        my $env = { PERL5LIB => join(':', @INC) };
+        my $pid = spawn([$^X, ($^W ? ('-w') : ()), "-M$cls", '-e',
+                                $cls.'::start(@ARGV)', '--', @argv],
+                        $env, { 0 => $in });
+        ((bless { io => $sock, impl => $cls }, __PACKAGE__), $pid);
+}
+
+1;