]> Sergey Matveev's repositories - public-inbox.git/log
public-inbox.git
3 years agolei: test SIGPIPE, stop xsearch workers on client abort
Eric Wong [Thu, 14 Jan 2021 07:06:15 +0000 (19:06 -1200)]
lei: test SIGPIPE, stop xsearch workers on client abort

The new test ensures consistency between oneshot and
client/daemon users.  Cancelling an in-progress result now also
stops xsearch workers to avoid wasted CPU and I/O.

Note the lei->atfork_child_wq usage changes, it is to workaround
a bug in Perl 5: http://nntp.perl.org/group/perl.perl5.porters/258784
<CAHhgV8hPbcmkzWizp6Vijw921M5BOXixj4+zTh3nRS9vRBYk8w@mail.gmail.com>

This switches the internal protocol to use SOCK_SEQPACKET
AF_UNIX sockets to prevent merging messages from the daemon to
client to run pager and kill/exit the client script.

3 years agocmd_ipc: support + test EINTR + EAGAIN, no FDs
Eric Wong [Thu, 14 Jan 2021 07:06:14 +0000 (19:06 -1200)]
cmd_ipc: support + test EINTR + EAGAIN, no FDs

We'll ensure our {send,recv}_cmd4 implementations are
consistent w.r.t. non-blocking and interrupted sockets.

We'll also support receiving messages without FDs associated
so we don't have to send dummy FDs to keep receivers from
reporting EOF.

3 years agolei: query: restore JSON output overview
Eric Wong [Sun, 10 Jan 2021 12:15:19 +0000 (12:15 +0000)]
lei: query: restore JSON output overview

This internal API is better suited for fork-friendliness (but
locking + dedupe still needs to be re-added).

Normal "json" is the default, though stream-friendly "concatjson"
and "jsonl" (AKA "ndjson" AKA "ldjson") all seem working
(though tests aren't working, yet).

For normal "json", the biggest downside is the necessity of a
trailing "null" element at the end of the array because of
parallel processes, since (AFAIK) regular JSON doesn't allow
trailing commas, unlike JavaScript.

3 years agolei_xsearch: transfer 4 FDs internally, drop IO::FDPass
Eric Wong [Sun, 10 Jan 2021 12:15:18 +0000 (12:15 +0000)]
lei_xsearch: transfer 4 FDs internally, drop IO::FDPass

It's easier to make the code more generic by transferring
all four FDs (std(in|out|err) + socket) instead of omitting
stdin.

We'll be reading from stdin on some imports, and possibly
outputting to stdout, so omitting stdin now would needlessly
complicate things.

The differences with IO::FDPass "1" code paths and the "4"
code paths used by Inline::C and Socket::MsgHdr are far too
much to support and test at the moment.

3 years agolei: run pager in client script
Eric Wong [Sun, 10 Jan 2021 12:15:17 +0000 (12:15 +0000)]
lei: run pager in client script

While most single keystrokes work fine when the pager is
launched from the background daemon, Ctrl-C and WINCH can cause
strangeness when connected to the wrong terminal.

3 years agolei: fork + FD cleanup
Eric Wong [Sun, 10 Jan 2021 12:15:16 +0000 (12:15 +0000)]
lei: fork + FD cleanup

Do a better job of closing FDs that we don't want shared with
the work queue workers.  We'll also fix naming and use
"atfork_prepare" instead of "atfork_parent" to match
pthread_atfork(3) naming.

3 years agolei: get rid of client {pid} field
Eric Wong [Sun, 10 Jan 2021 12:15:15 +0000 (12:15 +0000)]
lei: get rid of client {pid} field

Using kill(2) is too dangerous since extremely long
queries may mean the original PID of the aborted lei(1)
client process to be recycled by a new process.  It would
be bad if the lei_xsearch worker process issued a kill
on the wrong process.

So just rely on sending the exit message via socket.

3 years agoipc: drop unused fields, default sighandlers for wq
Eric Wong [Sun, 10 Jan 2021 12:15:14 +0000 (12:15 +0000)]
ipc: drop unused fields, default sighandlers for wq

Relying on signal handlers to kill a particular worker was a
laggy/racy idea and I gave up on the idea of targetting workers
explicitly and instead chose to make wq_worker_decr stop the
next idle worker ->wq_exit.

We will however attempt to support sending signals to
a process group.

3 years agoipc: fix IO::FDPass use with a worker limit of 1
Eric Wong [Sun, 10 Jan 2021 12:15:13 +0000 (12:15 +0000)]
ipc: fix IO::FDPass use with a worker limit of 1

IO::FDPass is our last choice for implementing the workqueue
because its lack of atomicity makes it impossible to guarantee
all requests of a single group hit a single worker out of many.

So the only way to use IO::FDPass for workqueues it to only have
a single worker.  A single worker still buys us a small amount
of parallelism because of the parent process.

3 years agoipc: start supporting sending/receiving more than 3 FDs
Eric Wong [Sun, 10 Jan 2021 12:15:12 +0000 (12:15 +0000)]
ipc: start supporting sending/receiving more than 3 FDs

Actually, sending 4 FDs will be useful for lei internal xsearch
work once we start accepting input from stdin.  It won't be used
with the lightweight lei(1) client, however.

For WWW (eventually), a single FD may be enough.

3 years agolei: query: ensure pager exit is instantaneous
Eric Wong [Sun, 10 Jan 2021 12:15:11 +0000 (12:15 +0000)]
lei: query: ensure pager exit is instantaneous

Improve interactivity and user experience by allowing the user
to return to the terminal immediately when the pager is exited
(e.g. hitting the `q' key in less(1)).

This is a massive change which restructures query handling to
allow parallel search when --thread expansion is in use and
offloading to a separate worker when --thread is not in use.

The Xapian query offload changes allow us to reenter the event
loop right away once the search(es) are shipped off to the work
queue workers.

This means the main lei-daemon process can forget the lei(1)
client socket immediately once it's handed off to worker
processes.

We now unblock SIGPIPE in query workers and send an exit(141)
response to the lei(1) client socket to denote SIGPIPE.

This also allows parallelization for users using "lei q" from
multiple terminals.

JSON output is currently broken and will need to be restructured
for more flexibility and fork-safety.

3 years agolei: fix oneshot TTY detection by passing STD*{GLOB}
Eric Wong [Sun, 10 Jan 2021 12:15:10 +0000 (12:15 +0000)]
lei: fix oneshot TTY detection by passing STD*{GLOB}

...  instead of STD*{IO}.  I'm not sure why *STDOUT{IO} being an
IO::File object disqualifies it from the "-t" perlop check
returning true on TTY, but it does.  So use *STDOUT{GLOB} for
now.

http://nntp.perl.org/group/perl.perl5.porters/258760
Message-ID: <X/kgIqIuh4ZtUZNR@dcvr>

3 years agolei: rename $w to $wpager for warning message
Eric Wong [Sun, 10 Jan 2021 12:15:09 +0000 (12:15 +0000)]
lei: rename $w to $wpager for warning message

Perl keeps track of the variable name for error messages
when auto-closing an FD fails, so this will help identify
the source of a close error..

3 years agoipc: DESTROY and wq_workers methods
Eric Wong [Sun, 10 Jan 2021 12:15:08 +0000 (12:15 +0000)]
ipc: DESTROY and wq_workers methods

We'll enable automatic cleanup when IPC classes go out-of-scope
to avoid leaving zombies around.

->wq_workers will be a useful convenience method to change
worker counts.

3 years agoipc: drop -ipc_parent_pid field
Eric Wong [Sun, 10 Jan 2021 12:15:07 +0000 (12:15 +0000)]
ipc: drop -ipc_parent_pid field

It is not used anywhere.

3 years agoipc: wq: support dynamic worker count change
Eric Wong [Sun, 10 Jan 2021 12:15:06 +0000 (12:15 +0000)]
ipc: wq: support dynamic worker count change

Increasing/decreasing workers count will be useful in
some situations.

3 years agoipc: eliminate ipc_worker_stop method
Eric Wong [Sun, 10 Jan 2021 12:15:05 +0000 (12:15 +0000)]
ipc: eliminate ipc_worker_stop method

We can just EOF the pipe, and instead rely on per-class
error handling to deal with uncommitted transactions and
what not.

3 years agoipc: work queue support via SOCK_SEQPACKET
Eric Wong [Sun, 10 Jan 2021 12:15:04 +0000 (12:15 +0000)]
ipc: work queue support via SOCK_SEQPACKET

This will allow any number of younger sibling processes to
communicate with older siblings directly without relying on a
mediator process.  This is intended to be useful for
distributing search work across multiple workers without caring
which worker hits it (we only care about shard members).

And any request sent with this will be able to hit any worker
without locking on our part.

Unix stream sockets with a listener were also considered;
binding to a file on the FS may confuse users given there's
already a socket path for lei(1).  Linux-only Abstract or
autobind sockets are rejected due to lack of portability.

SOCK_SEQPACKET via socketpair(2) was chosen since it's POSIX
2008 and available on FreeBSD 9+ in addition to Linux, and
doesn't require filesystem access.

3 years agoipc: avoid excessive evals
Eric Wong [Sun, 10 Jan 2021 12:15:03 +0000 (12:15 +0000)]
ipc: avoid excessive evals

We should not need an eval for warning with our code base.
Nowadays, dwaitpid() automatically does the right thing
regardless of whether we're in the event loop, so no eval
is needed there, either.

3 years agocmd_ipc: send FDs with buffer payload
Eric Wong [Sun, 10 Jan 2021 12:15:02 +0000 (12:15 +0000)]
cmd_ipc: send FDs with buffer payload

For another step in in syscall reduction, we'll support
transferring 3 FDs and a buffer with a single sendmsg/recvmsg
syscall using Socket::MsgHdr if available.

Beyond script/lei itself, this will be used for internal IPC
between search backends (perhaps with SOCK_SEQPACKET).  There's
a chance this could make it to the public-facing daemons, too.

This adds an optional dependency on the Socket::MsgHdr package,
available as libsocket-msghdr-perl on Debian-based distros
(but not CentOS 7.x and FreeBSD 11.x, at least).

Our Inline::C version in PublicInbox::Spawn remains the last
choice for script/lei due to the high startup time, and
IO::FDPass remains supported for non-Debian distros.

Since the socket name prefix changes from 3 to 4, we'll also
take this opportunity to make the argv+env buffer transfer less
error-prone by relying on argc instead of designated delimiters.

3 years agoipc: add support for asynchronous callbacks
Eric Wong [Sun, 10 Jan 2021 12:15:01 +0000 (12:15 +0000)]
ipc: add support for asynchronous callbacks

Similar to git->cat_async, this will let us deal with responses
asynchronously, as well as being able to mix synchronous and
asynchronous code transparently (though perhaps not optimally).

3 years agods: block signals when reaping
Eric Wong [Sun, 10 Jan 2021 12:15:00 +0000 (12:15 +0000)]
ds: block signals when reaping

This lets us call dwaitpid long before a process exits
and not have to wait around for it.

This is advantageous for lei where we can run dwaitpid on the
pager as soon as we spawn it, instead of waiting for a client
socket to go away on DESTROY.

3 years agolei q: deduplicate smsg
Eric Wong [Sun, 10 Jan 2021 12:14:59 +0000 (12:14 +0000)]
lei q: deduplicate smsg

We don't want duplicate messages in results overviews, either.

3 years agolei query + pagination sorta working
Eric Wong [Sun, 10 Jan 2021 12:14:58 +0000 (12:14 +0000)]
lei query + pagination sorta working

Parallelism and interactivity with pager + SIGPIPE needs work;
but results are shown and phrase search works without shell
users having to apply Xapian quoting rules on top of standard
shell quoting.

3 years agov2writable: exact discontiguous history handling
Eric Wong [Tue, 5 Jan 2021 01:29:10 +0000 (01:29 +0000)]
v2writable: exact discontiguous history handling

We've always temporarily unindexeded messages before reindexing
them again if there's discontiguous history.

This change improves the mechanism we use to prevent NNTP and
IMAP clients from seeing duplicate messages.

Previously, we relied on mapping Message-IDs to NNTP article
numbers to ensure clients would not see the same message twice.
This worked for most messages, but not for for messages with
reused or duplicate Message-IDs.

Instead of relying on Message-IDs as a key, we now rely on the
git blob object ID for exact content matching.  This allows
truly different messages to show up for NNTP|IMAP clients, while
still those clients from seeing the message again.

3 years agoaddress: pairs: new helper for JMAP (and maybe lei)
Eric Wong [Tue, 5 Jan 2021 09:04:37 +0000 (09:04 +0000)]
address: pairs: new helper for JMAP (and maybe lei)

Per JMAP RFC 8621 sec 4.1.2.3, we should be able to
denote the lack of a phrase/comment corresponding to an
email address with a JSON "null" (or Perl `undef').

  [
    { "name": "James Smythe", "email": "james@example.com" },
    { "name": null, "email": "jane@example.com" },
    { "name": "John Smith", "email": "john@example.com" }
  ]

The new "pairs" method just returns a 2 dimensional array
and the consumer will fill in the field names if necessary
(or not).

lei(1) may use the two dimensional array as-is for JSON output.

3 years agolei: use client env as-is, drop daemon-env command
Eric Wong [Tue, 5 Jan 2021 09:04:36 +0000 (09:04 +0000)]
lei: use client env as-is, drop daemon-env command

There may be subtle misbehaviours when mixing the existing
daemon env and the client-supplied env.  Just do the simplest
thing and use the client env as-is.

We'll also start the ->event_step callback since we'll need
to remember some things for long-lived commands.

3 years agolei: automatic pager support
Eric Wong [Tue, 5 Jan 2021 09:04:35 +0000 (09:04 +0000)]
lei: automatic pager support

Just like git, we'll start a pager when outputting to a terminal
for user-friendliness when reading many messages.

3 years agolei: completion: fix filename completion
Eric Wong [Tue, 5 Jan 2021 09:04:34 +0000 (09:04 +0000)]
lei: completion: fix filename completion

"-o default" is what we want from "complete", "-o filename" just
tells readline the result from the "_lei" function might be a
filename and quote appropriately.

3 years agoimap: fix uninitialized var on MSN search miss
Eric Wong [Tue, 5 Jan 2021 18:19:48 +0000 (18:19 +0000)]
imap: fix uninitialized var on MSN search miss

It seems only triggered by bots trying to steal information.

3 years agolei: improve idempotent "init" error message
Eric Wong [Mon, 4 Jan 2021 04:16:24 +0000 (04:16 +0000)]
lei: improve idempotent "init" error message

Showing "leistore.dir= already initialized" because $cur is
undefined isn't useful.

3 years agolei: fix opt_dash to pass non-dash args to @argv
Eric Wong [Mon, 4 Jan 2021 04:16:23 +0000 (04:16 +0000)]
lei: fix opt_dash to pass non-dash args to @argv

The special "<>" handling in Getopt::Long actually invokes the
callback for every single command-line arg, not just those
prefixed by "-".  This will let us pass arbitrary non-dashed
words for search queries so users can type queries naturally
without quoting (unless they want phrase search).

3 years agolei: prefer IO::FDPass over our Inline::C recv_3fds
Eric Wong [Sun, 3 Jan 2021 20:58:29 +0000 (20:58 +0000)]
lei: prefer IO::FDPass over our Inline::C recv_3fds

While our recv_3fds() implementation is more efficient
syscall-wise, loading Inline takes nearly 50ms on my machine
even after Inline::C memoizes the build.  The current ~20ms in
the fast path is barely acceptable to me, and 50ms would be
unusable.

Eventually, script/lei may invoke tcc(1) or cc(1) directly in
the fast path, but it needs @INC for the slow path, at least.

We'll encode the number of FDs into the socket name allow
parallel installations, for now.

3 years agosearchidxshard: use add_xapian directly for v2
Eric Wong [Sun, 3 Jan 2021 02:06:17 +0000 (02:06 +0000)]
searchidxshard: use add_xapian directly for v2

We can more clearly distinguish between v1 and v2-only code
paths this way, and may be able to save a few cycles this way.

3 years agoipc: switch to one-way pipes
Eric Wong [Sun, 3 Jan 2021 02:06:16 +0000 (02:06 +0000)]
ipc: switch to one-way pipes

This fixes a performance regression in multi-process v2 indexing
due to the switch to PublicInbox::IPC.  While Unix sockets are
fewer FDs to manage, pipes allow unprivileged processes to use
larger buffers (up to 1M) on out-of-the-box Linux instances.

A larger buffer via F_SETPIPE_SZ afforded by pipes was proven
valuable during v2 development in 2018 and continues to be
valuable when we get significant amounts of one-way traffic from
the producer parent to worker children.

Compression may be an option for systems without F_SETPIPE_SZ;
but it increases CPU usage with no memory bandwidth savings on
hosts where larger buffers are available.

3 years agouse Eml (or MIME) objects for all indexing paths
Eric Wong [Sun, 3 Jan 2021 02:06:15 +0000 (02:06 +0000)]
use Eml (or MIME) objects for all indexing paths

We don't need to be keeping the raw message around after it hits
git.  Shard work now relies on Storable (or Sereal) and all of
the indexing code relies on the Email::MIME-like API of Eml to
access interesting parts of the message.

Similarly, smsg->{raw_bytes} is no longer carried around and we
do the CRLF adjustment when setting smsg->{bytes}.

There's also a small simplification to t/import.t while
we're in the area to use xqx instead of spawn/popen_rd.

3 years agosearchidxshard: replace index_raw with index_eml
Eric Wong [Sun, 3 Jan 2021 02:06:14 +0000 (02:06 +0000)]
searchidxshard: replace index_raw with index_eml

Since Storable and Sereal are designed for lossless
serialization, we'll just pass $eml objects to whatever process
is running SearchIdx.

3 years agosearchidxshard: IPC conversion, part 2
Eric Wong [Sun, 3 Jan 2021 02:06:13 +0000 (02:06 +0000)]
searchidxshard: IPC conversion, part 2

We can remove some now-pointless wrapper functions by using
->ipc_do in even more places.

3 years agosearchidxshard: use PublicInbox::IPC to kill lots of code
Eric Wong [Sun, 3 Jan 2021 02:06:12 +0000 (02:06 +0000)]
searchidxshard: use PublicInbox::IPC to kill lots of code

It's nice to prove the new code works by swapping it into
the current V2Writable / SearchIdxShard packages.  This is
only the first step for the core bits, and we'll be able
to delete more code in a subsequent patch.

3 years agoipc: some documentation comments
Eric Wong [Sun, 3 Jan 2021 02:06:11 +0000 (02:06 +0000)]
ipc: some documentation comments

Fix some comments and add some short summary descriptions to
hopefully make things easier-to-follow.

3 years agogcf2client: split out request API from regular git
Eric Wong [Sun, 3 Jan 2021 02:12:06 +0000 (12:12 -1400)]
gcf2client: split out request API from regular git

While Gcf2Client is designed to mimic what git-cat-file writes
to stdout, its request format is different to support requests
with a git repository path included.

We'll highlight the distinction and make the GitAsyncCat support
code easier-to-follow as a result.

Since Gcf2Client relies on DS, we can rely on DS-specific code
here, too, and use a single Unix socket instead of separate
input and output pipes, reducing memory overhead in both users
and kernel space.  Due to the interactive nature of requests and
responses, the buffer size limitations of Unix sockets on Linux
seems inconsequential here (just like it is for existing "git
cat-file --batch" use).

3 years agolei: fix output race in client/daemon mode
Eric Wong [Sun, 3 Jan 2021 11:24:51 +0000 (11:24 +0000)]
lei: fix output race in client/daemon mode

The daemon needs to flush stdout before disconnecting or killing
clients, otherwise they may reread empty data on redirected
outputs.  We also don't want to unbuffer stdout too early in
case we have lots of small chunks of data to output.

The received ($self->{2}) will always have autoflush, matching normal
STDERR behavior.

3 years agosend and receive all 3 FDs at once
Eric Wong [Sun, 3 Jan 2021 11:24:50 +0000 (11:24 +0000)]
send and receive all 3 FDs at once

We'll always be transferring stdin, stdout, and stderr together
for lei.  Perhaps I lack imagination or foresight, but I can't
think of a reason to send more or less FDs.

3 years agospawn: support send_fd+recv_fd w/o IO::FDPass
Eric Wong [Sun, 3 Jan 2021 09:48:42 +0000 (09:48 +0000)]
spawn: support send_fd+recv_fd w/o IO::FDPass

IO::FDPass may be an extra installation burden I don't want to
impose on users.  We only support Linux and *BSDs, however.

3 years agotestcommon: prepare_redirects: fix error message
Eric Wong [Sun, 3 Jan 2021 09:48:41 +0000 (09:48 +0000)]
testcommon: prepare_redirects: fix error message

I never hit these die() calls, but noticed it while debugging
another problem on FreeBSD.

3 years agot/lei: use $lei->() callback wrapper
Eric Wong [Sun, 3 Jan 2021 09:48:40 +0000 (09:48 +0000)]
t/lei: use $lei->() callback wrapper

This shortens the test and should make it easier to debug and
add new tests.

3 years agoqspawn: switch to ProcessPipe via popen_rd
Eric Wong [Sat, 2 Jan 2021 09:13:44 +0000 (19:13 -1400)]
qspawn: switch to ProcessPipe via popen_rd

ProcessPipe has a built-in mechanism to prevent siblings from
reaping children.

3 years agogit: manifest_entry: use ProcessPipe via popen_rd
Eric Wong [Sat, 2 Jan 2021 09:13:43 +0000 (19:13 -1400)]
git: manifest_entry: use ProcessPipe via popen_rd

Only saves us one line of code, but that's better than nothing.

3 years agoimport: switch to using ProcessPipe
Eric Wong [Sat, 2 Jan 2021 09:13:42 +0000 (19:13 -1400)]
import: switch to using ProcessPipe

This saves us a few lines of code, but also prevents misreaping
by sibling processes.

3 years agogit: qx: waitpid synchronously via ProcessPipe->CLOSE
Eric Wong [Sat, 2 Jan 2021 09:13:41 +0000 (19:13 -1400)]
git: qx: waitpid synchronously via ProcessPipe->CLOSE

If we're using ->qx, we're operating synchronously anyways,
so there's little point in relying on the event loop for
waitpid.

3 years agoprocesspipe: lazy-require PublicInbox::DS for dwaitpid
Eric Wong [Sat, 2 Jan 2021 09:13:40 +0000 (19:13 -1400)]
processpipe: lazy-require PublicInbox::DS for dwaitpid

This saves over 20ms with scripts that only use PublicInbox::Spawn.

3 years agoprocesspipe: allow synchronous close to set $?
Eric Wong [Sat, 2 Jan 2021 09:13:39 +0000 (19:13 -1400)]
processpipe: allow synchronous close to set $?

To get rid of the ugly $PublicInbox::DS::in_loop localization
in MboxReader, we'll distinguish between ->CLOSE and ->DESTROY
with ProcessPipe.

If we end up closing via ->DESTROY, we'll assume the caller will
want to deal with $? asynchronously via the event loop (or not
even care about $?).

If we hit ->CLOSE directly, we'll assume the caller called
close() and wants to check $? synchronously.

Note: wantarray doesn't seem to propagate into tied methods,
otherwise I'd be relying on that.

3 years agolei_store: alternative unconfigured "git var" workaround
Eric Wong [Sat, 2 Jan 2021 08:32:04 +0000 (08:32 +0000)]
lei_store: alternative unconfigured "git var" workaround

While the changes to git->qx/git->popen from commit 171a9c24022ad7ef
will be useful for the lei daemon, hiding git error messages from
actual users is probably wrong and we'll just localize GIT_*
vars for testing.

3 years agotreewide: reduce load_xapian* callsites
Eric Wong [Fri, 1 Jan 2021 05:47:50 +0000 (17:47 -1200)]
treewide: reduce load_xapian* callsites

Hopefully this will make it easier to spot dependency
bugs in the future.

3 years agoimport: unset GIT_CONFIG with `git config --global'
Eric Wong [Fri, 1 Jan 2021 05:47:49 +0000 (17:47 -1200)]
import: unset GIT_CONFIG with `git config --global'

GIT_CONFIG is set by -convert, and user may have it set
for other reasons.  In either case, it conflicts with
any any attempt to use `git config --global` so we have
to unset it.

This fixes t/multi-mid.t under TEST_RUN_MODE=0

3 years agot/lei: fix TEST_RUN_MODE=0, simplify oneshot fallback
Eric Wong [Fri, 1 Jan 2021 05:47:48 +0000 (17:47 -1200)]
t/lei: fix TEST_RUN_MODE=0, simplify oneshot fallback

We need to use an absolute path after chdir in run modes
where scripts aren't loaded into in-memory subs.

The oneshot test was also failing under TEST_RUN_MODE=0 due to
no "lei-oneshot" command existing on the FS.  So we force a
socket failure by making XDG_RUNTIME_DIR too large to fit into
the 108-byte .sun_path field of "struct sockaddr_un".  This
even lets us simplify lei-oneshot significantly.

3 years agosearch: do not use $QP_FLAGS until Xapian is loaded
Eric Wong [Fri, 1 Jan 2021 05:47:47 +0000 (17:47 -1200)]
search: do not use $QP_FLAGS until Xapian is loaded

The default $QP_FLAGS won't be set until after Xapian is
loaded, duh...

This fixes t/imapd.t with TEST_RUN_MODE=0

3 years agolei_store: quiet down "git var" failures
Eric Wong [Fri, 1 Jan 2021 09:20:59 +0000 (19:20 -1400)]
lei_store: quiet down "git var" failures

$git->qx and $git->popen now $env and $opt for redirects
like lower-level popen_rd.  This may be beneficial in other
places.

3 years agoupdate copyrights for 2021
Eric Wong [Fri, 1 Jan 2021 05:13:18 +0000 (05:13 +0000)]
update copyrights for 2021

Using "make update-copyrights" after setting GNULIB_PATH in my
config.mak

3 years agoMakefile.PL: add update-copyrights target
Eric Wong [Fri, 1 Jan 2021 05:10:57 +0000 (05:10 +0000)]
Makefile.PL: add update-copyrights target

It might save me a few cycles every year to not have to
scroll through git history to see how it's run.

3 years agoon_destroy: support PID owner guard
Eric Wong [Thu, 31 Dec 2020 13:51:54 +0000 (13:51 +0000)]
on_destroy: support PID owner guard

Since we'll be forking for Xapian indexing and maybe
other places, having a simple guard in place to ensure
OnDestroy doesn't unexpectedly unlink files or similar
is a safer option.

3 years agods: clobber $in_loop first at reset
Eric Wong [Thu, 31 Dec 2020 13:51:53 +0000 (13:51 +0000)]
ds: clobber $in_loop first at reset

This may help ensure DESTROY callbacks will see in_loop
before the others.

3 years agoavoid calling waitpid from children in DESTROY
Eric Wong [Thu, 31 Dec 2020 13:51:52 +0000 (13:51 +0000)]
avoid calling waitpid from children in DESTROY

Objects with DESTROY callbacks get propagated to children, so we
must be careful to not invoke waitpid from children on their
sibling processes.  Only parents (and their parents...) can reap
child processes.

3 years agolei: avoid Spawn package when starting daemon
Eric Wong [Thu, 31 Dec 2020 13:51:51 +0000 (13:51 +0000)]
lei: avoid Spawn package when starting daemon

Spawn was designed to speed up process spawning inside
long-lived daemons with largish memory usage.  It does not help
for short-lived scripts which only exist to start and connect to
a daemon.

This change actually speeds up initial lei startup from
~190ms to ~140ms(!).  Normal usage once the daemon is running
is unaffected, at <20ms for help text.

While we're in the area, simplify Cwd error message generation,
too.

3 years agosyscall: SFD_NONBLOCK can be a constant, again
Eric Wong [Thu, 31 Dec 2020 13:51:50 +0000 (13:51 +0000)]
syscall: SFD_NONBLOCK can be a constant, again

Since Perl exposes O_NONBLOCK as a constant, we can safely make
SFD_NONBLOCK a constant, too.  This is not the case for
SFD_CLOEXEC, since O_CLOEXEC is not exposed by Perl despite
being used internally in the interpreter.

3 years agouse PublicInbox::DS for dwaitpid
Eric Wong [Thu, 31 Dec 2020 13:51:49 +0000 (13:51 +0000)]
use PublicInbox::DS for dwaitpid

This simplifies our code and provides a more consistent API for
error handling.  PublicInbox::DS can be loaded nowadays on all
*BSDs and Linux distros easily without extra packages to
install.

The downside is possibly increased startup time, but it's
probably not as a big problem with lei being a daemon
(and -mda possibly following suite).

3 years agot/ipc.t: test for references via `die'
Eric Wong [Thu, 31 Dec 2020 13:51:48 +0000 (13:51 +0000)]
t/ipc.t: test for references via `die'

We'll probably start using references as exceptions in
some places for more exact matching.

3 years agosearchidxshard: call DS->Reset at worker start
Eric Wong [Thu, 31 Dec 2020 13:51:47 +0000 (13:51 +0000)]
searchidxshard: call DS->Reset at worker start

The daemon for the local email interface will be inside
the DS->EventLoop.  -watch currently doesn't trigger this
bug since it doesn't enable parallelism, but it may in
the future.

3 years agolei_to_mail: open FIFOs O_WRONLY so we block
Eric Wong [Thu, 31 Dec 2020 13:51:46 +0000 (13:51 +0000)]
lei_to_mail: open FIFOs O_WRONLY so we block

Opening a FIFO with O_RDWR always succeeds on Linux, which
cause the cat(1) process invoked by t/lei_to_mail.t to get
stuck.  Furthermore O_APPEND makes no sense on FIFOs and
perhaps there's some kernel out there which will reject it.

3 years agogcf2client: reap process on DESTROY
Eric Wong [Thu, 31 Dec 2020 13:51:45 +0000 (13:51 +0000)]
gcf2client: reap process on DESTROY

We don't want to leave Xapcmd waitpid(-1, ...) call to hit it.

3 years agot/run: avoid uninitialized var on incomplete test
Eric Wong [Thu, 31 Dec 2020 13:51:44 +0000 (13:51 +0000)]
t/run: avoid uninitialized var on incomplete test

Diagnosing an occasional FIFO failure in t/lei_to_mail.t...

3 years agoinit: remove embedded UnlinkMe package
Eric Wong [Thu, 31 Dec 2020 13:51:43 +0000 (13:51 +0000)]
init: remove embedded UnlinkMe package

PublicInbox::OnDestroy can do the same thing

3 years agospawn: move run_die here from PublicInbox::Import
Eric Wong [Thu, 31 Dec 2020 13:51:42 +0000 (13:51 +0000)]
spawn: move run_die here from PublicInbox::Import

It seems like a more logical place for it, but we'll favor the
newly-added xsys_e() in tests for BAIL_OUT use.

3 years agolei: add --mfolder as an --output alias
Eric Wong [Thu, 31 Dec 2020 13:51:41 +0000 (13:51 +0000)]
lei: add --mfolder as an --output alias

This will be helpful for mairix users.

3 years agolei_to_mail: unlink mboxes if not augmenting
Eric Wong [Thu, 31 Dec 2020 13:51:40 +0000 (13:51 +0000)]
lei_to_mail: unlink mboxes if not augmenting

This matches mairix(1) behavior and may be safer if there's
concurrent readers on the existing mbox, especially since
we don't do currently implement mbox locking (nor does mairix).

3 years agoipc: use shutdown(2), base atfork* callback
Eric Wong [Thu, 31 Dec 2020 13:51:39 +0000 (13:51 +0000)]
ipc: use shutdown(2), base atfork* callback

shutdown(2) on a socket can be preferable if there's multiple
forked processes writing to a single worker and we really want
to shut things down ASAP.

It may also be good to provide an ipc_worker_exit method which
subclasses can override if needed for graceful shutdown.  But we
won't need equivalents to atexit(3) since we can rely on DESTROY
handlers given this is Perl5.

3 years agolei_store: handle messages without Message-ID at all
Eric Wong [Thu, 31 Dec 2020 13:51:38 +0000 (13:51 +0000)]
lei_store: handle messages without Message-ID at all

For personal mail, unsent drafts messages are a common source of
messages without Message-IDs.

3 years agomid: hoist out mids_in sub
Eric Wong [Thu, 31 Dec 2020 13:51:37 +0000 (13:51 +0000)]
mid: hoist out mids_in sub

We'll be using it for Resent-Message-ID with lei, and possibly
other places.

3 years agomid: use defined-or with `push' for uniqueness check
Eric Wong [Thu, 31 Dec 2020 13:51:36 +0000 (13:51 +0000)]
mid: use defined-or with `push' for uniqueness check

As shown recently in commit a05445fb400108e60ede7d377cf3b26a0392eb24
("config: config_fh_parse: micro-optimize"), the relying on
the return value of `push' and defined-or operators can avoid
modifying a the hash value scalar with an increment.

3 years agolei: rename "extinbox" => "external"
Eric Wong [Thu, 31 Dec 2020 13:51:35 +0000 (13:51 +0000)]
lei: rename "extinbox" => "external"

The words "extinbox" and "extindex" are too close and easy to
confuse with the other.  Rename "extinbox" to "external", since
these could be IMAP, JMAP or other non-public-inbox search APIs.

Link: https://public-inbox.org/meta/20201226112649.GB6226@dcvr/
3 years agolei_store: add ->set_eml, ->add_eml can return smsg
Eric Wong [Thu, 31 Dec 2020 13:51:34 +0000 (13:51 +0000)]
lei_store: add ->set_eml, ->add_eml can return smsg

Add a ->set_eml method which can be a useful fire-and-forget
way of either adding new files to store OR setting keywords
on them.

When seeing brand-new messages, add_eml can afford to return
more information in the smsg instead of just the OID.

3 years agoipc: support Sereal
Eric Wong [Thu, 31 Dec 2020 13:51:33 +0000 (13:51 +0000)]
ipc: support Sereal

Some testing will be needed to see if it's worth the code
and maintenance overhead, but it seems easy-enough to get
working.

3 years agoipc: generic IPC dispatch based on Storable
Eric Wong [Thu, 31 Dec 2020 13:51:32 +0000 (13:51 +0000)]
ipc: generic IPC dispatch based on Storable

I intend to use this with LeiStore when importing from multiple
slow sources at once (e.g. curl, IMAP, etc).  This is because
over.sqlite3 can only have a single writer, and we'll have
several slow readers running in parallel.

Watch and SearchIdxShard should also be able to use this code
in the future, but this will be proven with LeiStore, first.

3 years agolei_to_mail: support Maildir, fix+test --augment
Eric Wong [Thu, 31 Dec 2020 13:51:31 +0000 (13:51 +0000)]
lei_to_mail: support Maildir, fix+test --augment

Maildir should be plenty fine for short-lived output folders.

3 years agolei_to_mail: support for non-seekable outputs
Eric Wong [Thu, 31 Dec 2020 13:51:30 +0000 (13:51 +0000)]
lei_to_mail: support for non-seekable outputs

Users may wish to pipe output to "git am", "spamc",
or similar, so we need to support those cases and
not bail out on lseek(2) or ftruncate(2) failures.

3 years agolei_to_mail: lazy-require LeiDedupe
Eric Wong [Thu, 31 Dec 2020 13:51:29 +0000 (13:51 +0000)]
lei_to_mail: lazy-require LeiDedupe

LeiDedupe requires SQLite, so we may want to be able to test
writing mail without DBI or SQLite down the line.

3 years agolei: implement various deduplication strategies
Eric Wong [Thu, 31 Dec 2020 13:51:28 +0000 (13:51 +0000)]
lei: implement various deduplication strategies

For writing mboxes and Maildirs, users may wish to use
stricter or looser deduplication strategies.  This
gives them more control.

3 years agolei_to_mail: start --augment, dedupe, bz2 and xz
Eric Wong [Thu, 31 Dec 2020 13:51:27 +0000 (13:51 +0000)]
lei_to_mail: start --augment, dedupe, bz2 and xz

--augment will match the mairix(1) option of the same
name to augment existing search results.  We'll need
to implement deduplication for a better user experience.

mutt ships with compressed mbox support for bz2 and xz,
at least, so we'll support those out-of-the-box.

3 years agomboxreader: new class for reading various mbox formats
Eric Wong [Thu, 31 Dec 2020 13:51:26 +0000 (13:51 +0000)]
mboxreader: new class for reading various mbox formats

This is only lightly-tested against stuff LeiToMail generates
and will need real-world tests to validate.

3 years agolei_to_mail: start atomic and compressed mbox writing
Eric Wong [Thu, 31 Dec 2020 13:51:25 +0000 (13:51 +0000)]
lei_to_mail: start atomic and compressed mbox writing

We'll allow using multiple workers to write to a single
mbox (which could be compressed).  This is can be done
safely with O_APPEND + syswrite for uncompressed files,
and using a lock when piping to pigz/gzip/bzip2/xz.

3 years agosharedkv: split out index_values
Eric Wong [Thu, 31 Dec 2020 13:51:24 +0000 (13:51 +0000)]
sharedkv: split out index_values

In most cases, we won't need to index by value, so
don't waste cycles or space on it.

3 years agosharedkv: fork()-friendly key-value store
Eric Wong [Thu, 31 Dec 2020 13:51:23 +0000 (13:51 +0000)]
sharedkv: fork()-friendly key-value store

This is intended for maintaining Maildir states, mbox message
deduplication, but may be useful for other purposes...

3 years agolei_to_mail: initial implementation for writing mbox formats
Eric Wong [Thu, 31 Dec 2020 13:51:22 +0000 (13:51 +0000)]
lei_to_mail: initial implementation for writing mbox formats

No Maildir, support, yet, but it'll come.

3 years agorevert "lei_store: use per-machine refname as git HEAD"
Eric Wong [Thu, 31 Dec 2020 13:51:21 +0000 (13:51 +0000)]
revert "lei_store: use per-machine refname as git HEAD"

In retrospect, per-machine HEADs was a bad idea because users
of removable storage would be thrown off when moving storage
between different machines.

This is only a partial revert, the Import::init_bare change to
support alternate head names still exists because we may use it
for other reasons.

3 years agolei_store: use per-machine refname as git HEAD
Eric Wong [Thu, 31 Dec 2020 13:51:20 +0000 (13:51 +0000)]
lei_store: use per-machine refname as git HEAD

It may be helpful to identify the source of messages
and perhaps avoid conflicting history.

On the other hand, this may be a terrible idea for users who
move portable storage (e.g. USB sticks) across computers...

3 years agoimport: respect init.defaultBranch
Eric Wong [Thu, 31 Dec 2020 13:51:19 +0000 (13:51 +0000)]
import: respect init.defaultBranch

This matches git v2.28.0+ behavior in case users prefer
a different name.

3 years agoMerge remote-tracking branch 'origin/lei' into eidx
Eric Wong [Fri, 1 Jan 2021 04:58:39 +0000 (04:58 +0000)]
Merge remote-tracking branch 'origin/lei' into eidx

* origin/lei: (28 commits)
  lei: rename proposed "query" command to "q", add JSON output
  lei_xsearch: cross-(inbox|extindex) search
  lei: extinbox: start implementing in config file
  lei: revise output routines
  lei: support for -$DIGIT and -$SIG CLI switches
  build: add lei.sh + "make symlink-install" target
  lei: start working on bash completion
  lei: drop $SIG{__DIE__}, add oneshot fallbacks
  lei: restore default __DIE__ handler for event loop
  on_destroy: generic localized END
  lei_store: keyword extraction from mbox and Maildir
  lei_store: relax GIT_COMMITTER_IDENT check
  lei: micro-optimize startup time
  lei: rename $client => $self and bless
  lei: help: show actual paths being operated on
  lei: support pass-through for `lei config'
  rename LeiDaemon package to PublicInbox::LEI
  search: simplify initialization, add ->xdb_shards_flat
  lei_store: simplify git_epoch_max, slightly
  lei: support `daemon-env' for modifying long-lived env
  ...

3 years agoMerge tag 'v1.6.1' into eidx
Eric Wong [Fri, 1 Jan 2021 04:51:46 +0000 (04:51 +0000)]
Merge tag 'v1.6.1' into eidx

public-inbox 1.6.1 - minor bugfix release

* tag 'v1.6.1': (31 commits)
  public-inbox 1.6.1 - minor bugfix release
  import: drop X-Status in addition to Status
  eml: fix undefined vars on <Perl 5.28
  t/config: test --get-urlmatch for git <2.26
  inboxidle: avoid needless syscalls on refresh
  inboxidle: clue users into resolving ENOSPC from inotify
  inbox: name variable for values loop iterator
  public-inbox-v[12]-format.pod: make lexgrog happy
  manifest.js.gz: fix per-inbox /$INBOX/manifest.js.gz
  Fix manpage section of perl module documentation
  t/psgi_v2: ignore warnings on missing P::M::ReverseProxy
  daemon: support --daemonize without Net::Server::Daemonize
  doc: v2-format: drop repeated word
  over: ensure old, merged {tid} is really gone
  wwwattach: prevent deep-linking via Referer match
  t/eml.t: workaround newer Email::MIME* behavior
  nntp: attempt RFC 5536 3.1.5-conformant Path: headers
  nntp: delimit Newsgroup: header with commas
  tls: epollbit: account for miscellaneous OpenSSL errors
  scripts/dupe-finder: restore $dbh variable
  ...

3 years agopublic-inbox 1.6.1 - minor bugfix release v1.6.1
Eric Wong [Thu, 31 Dec 2020 20:15:28 +0000 (20:15 +0000)]
public-inbox 1.6.1 - minor bugfix release

3 years agoMerge remote-tracking branch 'origin/master' into lorelei
Eric Wong [Thu, 31 Dec 2020 13:24:36 +0000 (13:24 +0000)]
Merge remote-tracking branch 'origin/master' into lorelei

* origin/master: (58 commits)
  ds: flatten + reuse @events, epoll_wait style fixes
  ds: simplify EventLoop implementation
  check defined return value for localized slurp errors
  import: check for git->qx errors, clearer return values
  git: qx: avoid extra "local" for scalar context case
  search: remove {mset} option for ->mset method
  search: remove pointless {relevance} setting
  miscsearch: take reopen from Search and use it
  extsearch: unconditionally reopen on access
  extindex: allow using --all without EXTINDEX_DIR
  extindex: add undocumented --no-scan switch
  extindex: enable autoflush on STDOUT/STDERR
  extindex: various --watch signal handling fixes
  extindex: --watch for inotify-based updates
  eml: fix undefined vars on <Perl 5.28
  t/config: test --get-urlmatch for git <2.26
  default to CORE::warn in $SIG{__WARN__} handlers
  inbox: name variable for values loop iterator
  inboxidle: avoid needless syscalls on refresh
  inboxidle: clue users into resolving ENOSPC from inotify
  ...