Eric Wong [Sat, 25 Jan 2020 04:45:08 +0000 (04:45 +0000)]
viewdiff: add "b=" param when missing "diff --git" line
<2841d2de-32ad-eae8-6039-9251a40bb00e@tngtech.com> as posted to
git@vger contained an otherwise valid diff without a "diff
--git" line. Generate a "b=" parameter in that case using the
"+++" line instead of the "diff --git" line. SearchIdx.pm no
longer uses the "diff --git" line for filename information,
either.
Eric Wong [Sat, 25 Jan 2020 04:45:07 +0000 (04:45 +0000)]
viewdiff: add "b=" param with non-standard diff prefix
<20180228012207.GB251290@aiede.svl.corp.google.com> (posted to
git@vger) uses "i" and "w" prefixes instead of the standard "a"
and "b" prefixes, ensure we emit a "b=$FILENAME" param for the
solver endpoint to improve search accuracy, syntax highlighting,
and information density in the URL itself.
Eric Wong [Sat, 25 Jan 2020 04:45:04 +0000 (04:45 +0000)]
linkify: move to_html over from ViewDiff
We use the same idiom in many places for doing two-step
linkification and HTML escaping. Get rid of an outdated
comment in flush_quote while we're at it.
Eric Wong [Sat, 25 Jan 2020 04:45:01 +0000 (04:45 +0000)]
xt/perf-msgview: switch to multipart_text_as_html
It's a more widely-used (but still internal) API which will
probably last longer than msg_html. It also reaches deeper into
the stack and avoids the overhead of ->getline via PSGI, so it's
faster and gives a more accurate measurement of lower-level parts.
Eric Wong [Sat, 25 Jan 2020 04:45:00 +0000 (04:45 +0000)]
tests: move the majority of t/view.t into t/plack.t
And some more into t/mid.t. PublicInbox::View::msg_html may
change internally, so lets rely on the stable PSGI interface
to test it, rather than a test which reaches deep into the
internals.
Eric Wong [Sat, 25 Jan 2020 04:44:56 +0000 (04:44 +0000)]
wwwstream: discard single-use $ctx fields after use
This should make it clear that we only use these elements
once and can discard them. While we're in the area, avoid
escaping '"' by using qq() instead of "" to quote strings
requiring interpolation.
Eric Wong [Sat, 25 Jan 2020 04:44:52 +0000 (04:44 +0000)]
searchview: keep $noop sub private to the package
It'll always be used as a callback, so there's no point in
giving it a name to be called non-anonymously. Making
assigments to it is slightly faster since there's no need
to repeatedly do a lookup by name.
Eric Wong [Sun, 26 Jan 2020 01:17:44 +0000 (01:17 +0000)]
xapcmd: increase scope of lock
The old lock scope was only sufficient for protecting against
concurrent modifications from the common -mda, -watch, or -learn
writers.
It was not sufficient for protecting against parallel -compact
or -xcpdb invocations from eager admins. Most of the time this
only leads to confusing and misleading warning messages, but
parallel xcpdb --reshard could lead to errors.
Eric Wong [Sun, 26 Jan 2020 01:17:43 +0000 (01:17 +0000)]
search: {version} => {ibx_ver}
We don't confuse human readers with the Xapian schema version.
We also want to make it obvious this is the version of the inbox
we're indexing, these are Search or SearchIdx objects, not Inbox
objects.
Eric Wong [Sat, 25 Jan 2020 20:57:57 +0000 (20:57 +0000)]
switch to sysseek + sysread for serving static files
The "perlio" layer doesn't do read(2) syscalls over 8192 bytes
at the moment, and binmode($fh, ':unix') leaks[1]. So use
sysseek and sysread for now, since I can't see retaining
compatibility with PerlIO::scalar being worth the trouble.
Eric Wong [Fri, 24 Jan 2020 09:43:52 +0000 (09:43 +0000)]
wwwstatic: wire up buffer bypass for -httpd
This prevents public-inbox-httpd from buffering ->getline
results from a static file into another temporary file when
writing to slow clients. Instead we inject the static file
ref with offsets and length directly into the {wbuf} queue.
It took me a while to decide to go this route, some
rejected ideas:
1. Using Plack::Util::set_io_path and having PublicInbox::HTTP
serve the result directly. This is compatible with what
some other PSGI servers do using sendfile. However, neither
Starman or Twiggy currently use sendfile for partial responses.
2. Parsing the Content-Range response header for offsets and
lengths to use with set_io_path for partial responses.
These rejected ideas required increasing the complexity of HTTP
response writing in PublicInbox::HTTP in the common, non-static
file cases. Instead, we made minor changes to the colder write
buffering path of PublicInbox::DS and leave the hot paths
untouched.
We still support generic PSGI servers via ->getline. However,
since we don't know the characteristics of other PSGI servers,
we no longer do a 64K initial read in an attempt to negotiate a
larger TCP window.
Eric Wong [Fri, 24 Jan 2020 09:43:51 +0000 (09:43 +0000)]
ds: tmpio: store offsets per-buffer
We want to be able to inject existing file handles + offsets and
even lengths into this in the future, without going through the
->getline interface[1]
We also switch to using a 64K buffer size since we can safely
discard whatever got truncated on write and full writes can help
negotiate a larger TCP window for high-latency, high-bandwidth
links.
While we're at it, make it obvious that we're using O_APPEND for
our tmpfile() interface so we can seek freely for reading while
the writer always prints to the end of the file.
[1] the getline interface for serving static files may result
in us buffering on-FS data into another temporary file,
which is a waste.
Eric Wong [Fri, 24 Jan 2020 09:43:50 +0000 (09:43 +0000)]
wwwstatic: offload error handling to PSGI server
The PSGI server needs to account for ->getline failing
due to disk failures or truncated files, anyways. So
just die() ourselves and let the PSGI server log and
drop the client.
Eric Wong [Fri, 24 Jan 2020 22:09:32 +0000 (22:09 +0000)]
website: omit technical/ and other subdirs
We don't need to clutter the website with unnecessary technical
information. Anybody who reads the technical/ directory should
be looking at our source code, anyways; and we also have cgit
and gitweb mirrors.
Eric Wong [Fri, 24 Jan 2020 22:09:29 +0000 (22:09 +0000)]
doc: avoid needless rebuilds of NEWS
Repeatedly rebuilding `NEWS' because the mtime of `NEWS'
is synched to the latest release .eml is a bit annoying,
but necessary to save bandwidth for the website.
So we'll also update the mtime of the source .eml file when
reading them. It's kinda gross to be setting mtimes of source
.eml files in Documentation/RelNotes/, but I can't think of
anything better at the moment...
Eric Wong [Thu, 23 Jan 2020 23:05:59 +0000 (23:05 +0000)]
contentid: ignore duplicate References: headers
OverIdx::parse_references already skips duplicate
References (which we use in SearchThread for rendering).
So there's no reason for our content deduplication logic
to care if a Message-Id in the Reference header is mentioned
twice.
Eric Wong [Thu, 23 Jan 2020 23:05:57 +0000 (23:05 +0000)]
mid: shorten uniq_mids logic
We won't be able to use List::Util::uniq here, but we can still
shorten our logic and make it more consistent with the rest of
our code which does similar things.
Eric Wong [Sun, 12 Jan 2020 21:17:56 +0000 (21:17 +0000)]
sigfd: simplify loop and improve documentation
We can use the return value of sysread to bound our loop instead
of repeatedly shortening the string. Furthermore add some
comments which can be easily checked against the signalfd(2)
manpage.
Eric Wong [Sun, 12 Jan 2020 21:17:55 +0000 (21:17 +0000)]
ds: flatten $EXPMAP, delete entries on close
We can reduce the amount of small arrayrefs in memory
by flattening $EXPMAP. This forces us to properly clean
up references during deferred close handling, so NNTP
(and soon HTTP) connections no longer linger until expiry.
Eric Wong [Sun, 12 Jan 2020 21:17:51 +0000 (21:17 +0000)]
ds|http|nntp: simplify {wbuf} population
We can rely on autovification to turn `undef' value of {wbuf}
into an arrayref.
Furthermore, "push" returns the (new) size of the array since at
least Perl 5.0 (I didn't look further back), so we can use that
return value instead of calling "scalar" again.
Eric Wong [Sun, 12 Jan 2020 21:17:50 +0000 (21:17 +0000)]
ds: guard ToClose against DESTROY side-effects
This does not affect our current code, but theoretically a
DESTROY callback could call PublicInbox::DS::close to enqueue
elements into the ToClose array. So take a similar strategy as
we do with other queues (e.g. $nextq) by swapping references to
arrays, rather than operating on the array itself.
Since close operations are relatively rare, we can rely on
auto-vivification via "push" ops to create the array on an
as-needed basis.
Since we're in the area, clean up the PostLoopCallback
invocation to use the ternary operator rather than a confusing
(to me) combination of statements.
Finally, add a prototype to strengthen compile-time checking,
and move it in front of our only caller to make use of
the prototype.
Eric Wong [Sun, 12 Jan 2020 21:17:47 +0000 (21:17 +0000)]
ds: add_timer: rename from AddTimer, remove a parameter
The class parameter is pointless, especially for an internal
sub which only has one external caller in a test. Add a sub
prototype while we're at it to get some compile time checking.
Eric Wong [Sun, 12 Jan 2020 21:17:46 +0000 (21:17 +0000)]
ds: new: avoid redundant check, make clobbering fatal
"fileno(undef)" already dies under "use strict", so there's no
need to check for it ourselves. As far as "fileno($closed_io)"
or "fileno($fake_io)" goes, we'll let epoll_ctl detect the
error, instead.
Our design should make DescriptorMap entries impossible to clobber,
so make it fatal via confess in case it does happen, because
inadvertantly clobbering a FD would be very bad. While we're at
it, remove a redundant return statement and rely on implicit
returns.
Eric Wong [Sat, 11 Jan 2020 22:35:03 +0000 (22:35 +0000)]
use popen_rd for bidirectional pipes
popen_rd accepts arbitrary redirects, so we can reuse its
code to setup the pipe end we want to read, saving each
caller a few lines of code compared to calling pipe+spawn.
Eric Wong [Sat, 11 Jan 2020 22:35:00 +0000 (22:35 +0000)]
xapcmd: use popen_rd for running xapian-compact
public-inbox-compact wrapper displays progress by default,
anyways, and there's not a lot of output, so simplify our
code by using popen_rd instead of spawn + optional pipe.
While we're at it use "while (<HANDLE>)" to display
progress as it happens, since "foreach (<$HANDLE>)"
slurps the contents into an array, first.
Eric Wong [Sat, 11 Jan 2020 22:34:59 +0000 (22:34 +0000)]
cgit: drop cgit_parse_hdr wrapper
Unlike PublicInbox::GitHTTPBackend::git_parse_hdr,
cgit_parse_hdr does nothing interesting besides calling
parse_cgi_headers. So just make a reference to
PublicInbox::GitHTTPBackend::parse_cgi_headers and call it.
Eric Wong [Sat, 11 Jan 2020 22:34:55 +0000 (22:34 +0000)]
config: do not slurp entire cgitrc at once
cgitrc files can have hundreds or thousands of lines in them and
slurping them into memory is a waste. "while (<$fh>)" only
reads one line at a time, whereas "for (<$fh>)" reads the entire
contents of the file into a temporary array.
Eric Wong [Fri, 10 Jan 2020 22:55:30 +0000 (22:55 +0000)]
examples/unsubscribe.milter: support unique mailto:
Instead of providing a generic "mailto:foo+unsubscribe@example.com"
address in List-Unsubscribe which requires confirmation, replace it
with a mailto: header with a unique subject which contains the same
unique ID we put in the https:// URL.
This makes it easier for some MUAs without https:// support to
unsubscribe with a single action via the List-Unsubscribe header.
Eric Wong [Fri, 10 Jan 2020 22:55:29 +0000 (22:55 +0000)]
examples/unsubscribe.milter: skip gmane-mx
Mail to gmane is being delivered to gmane-mx.org, nowadays, and
we don't want ordinary readers to be able to trigger unconfirmed
unsubscription off any mailing lists which go through our
unsubscribe.milter.
Eric Wong [Sat, 11 Jan 2020 06:28:16 +0000 (06:28 +0000)]
www: discard multipart parent on iteration
We're often iterating through messages while writing to another
buffer in our WWW interface, causing memory usage to multiply.
Since we know we won't need to keep the MIME object around in
some cases, and can tell msg_iter to clobber the on-stack
variable while it operates on subparts of multipart messages.
With xt/mem-msgview.t switched to multipart from the previous
commit, this shows a 13 MB memory reduction on that test.
Eric Wong [Sat, 11 Jan 2020 06:28:15 +0000 (06:28 +0000)]
xt/mem-msgview.t: change to test one multipart message
A single multipart message is far more common than
a reused Message-ID, so rewrite the test to only have
a single multipart message. Memory improvements will
be implemented in the next commit.
Eric Wong [Fri, 10 Jan 2020 08:49:32 +0000 (08:49 +0000)]
make Filesys::Notify::Simple optional
It's only used by us in public-inbox-watch, and maybe not
for long. It's in most installations because Plack pulls it
in though, but Plack is no longer required.
Danga::Socket 1.62 was released a few months back and
the maintainer indicated it would be the last release.
We've diverged significantly in incompatible ways...
While most of this should've already been documented in
commit messages, putting it all into one document could
make it easier-to-digest.
It's also a strange design for anybody used to conventional
event loops. Maybe this is an unconventional project :P
Eric Wong [Fri, 10 Jan 2020 09:14:19 +0000 (09:14 +0000)]
spawn (and thus popen_rd) die on failure
Most spawn and popen_rd callers die on failure to spawn,
anyways, and some are missing checks entirely. This saves
us a bunch of verbose error-checking code in callers.
This also makes popen_rd more consistent, since it already
dies on pipe creation failures.
Eric Wong [Fri, 10 Jan 2020 09:14:17 +0000 (09:14 +0000)]
git: ->modified uses cat_async
While v1 inboxes are typically only a single branch, coderepos
will have many branches and being able to pipeline requests
to "git cat-file --batch" can help us mask seek times.
Eric Wong [Thu, 9 Jan 2020 11:14:52 +0000 (11:14 +0000)]
qspawn: catch transient errors on pipe, EPOLL_CTL_ADD
popen_rd dies on pipe()/pipe2() failure due to FD exhaustion.
EPOLL_CTL_ADD (via PublicInbox::HTTPD::Async->new) may also fail
due to memory exhaustion or exceeding the value of
/proc/sys/fs/epoll/max_user_watches
Eric Wong [Wed, 8 Jan 2020 10:44:09 +0000 (10:44 +0000)]
nntp: correctly log long response errors
We cannot safely call "fileno(undef)" without bringing down the
entire -nntpd process :x. To ensure no logging regression, we
now stash the FD for the duration of the long response to ensure
the error can be matched to the original command in logs.
Fixes: 207b89615a1a0c06 ("nntp: remove cyclic refs from long_response")
Eric Wong [Sun, 5 Jan 2020 23:23:36 +0000 (23:23 +0000)]
syscall: modernize away from pre-Perl-5.6 conventions
"use vars" was superseded by "our" in Perl 5.6, and we
can "use parent qw(Exporter)" in favor of manipulating
@ISA directly (or the bigger "use base ...");
While we're at it, avoid multiple invocations of constant->import
by passing a hashref as a "use" parameter.
Eric Wong [Sun, 5 Jan 2020 23:23:35 +0000 (23:23 +0000)]
treewide: "require" + "use" cleanup and docs
There's a bunch of leftover "require" and "use" statements we no
longer need and can get rid of, along with some excessive
imports via "use".
IO::Handle usage isn't always obvious, so add comments
describing why a package loads it. Along the same lines,
document the tmpdir support as the reason we depend on
File::Temp 0.19, even though every Perl 5.10.1+ user has it.
While we're at it, favor "use" over "require", since it it gives
us extra compile-time checking.
Eric Wong [Sun, 5 Jan 2020 23:23:33 +0000 (23:23 +0000)]
altid: use msgmap at compile time
AltId requires Msgmap to work, which requires SQLite. Search
also requires SQLite3 (for Over), nowadays, so there's no reason
for us to lazy-load Msgmap and SQLite anymore.
Eric Wong [Sun, 5 Jan 2020 23:23:32 +0000 (23:23 +0000)]
view: update POSIX::strftime usage
The POSIX module is always loaded, so import `strftime' into the
namespace so we can use it and take advantage of compile-time
arg checking. While we're at it, update and reorder caller
functions to use prototypes, too.
Eric Wong [Sun, 5 Jan 2020 23:23:31 +0000 (23:23 +0000)]
hval: export prurl and add prototype
This allows to do some compile-time checking and fills in a
missing "use" in PublicInbox::NewsWWW, allowing it to be used
standalone and independently of PublicInbox::WWW
Eric Wong [Sun, 5 Jan 2020 09:51:16 +0000 (09:51 +0000)]
view: msg_html: reduce memory use on reused MIDs
In rare cases where Message-IDs get reused, we do not want to
hold onto the large Email::MIME objects in memory after showing
the first message. So discard each message as soon as we're
done using it so we can save memory for the next message.
The new and expensive xt/mem-msgview.t test shows a nearly 14MB
reduction for two ~7MB messages. run_script() also gets
upgraded to make it easier to pass large inputs via IO GLOBs.
Eric Wong [Sat, 4 Jan 2020 22:54:00 +0000 (22:54 +0000)]
tests: remove some "git config" calls after "git init"
Creating a hash and iterating through it just to run "git
config" is ugly and slow. Just write out the text file in a
human-friendly way since the git-config file format is stable
and won't break randomly.
Eric Wong [Sat, 4 Jan 2020 09:16:21 +0000 (09:16 +0000)]
viewdiff: do not anchor spaces after filenames in diffstat
Viewing a CSS-less page in a browser which underlines links
can show a long line of underscores after diffstats. Not all
browsers underline links by default, though.
Eric Wong [Fri, 3 Jan 2020 08:46:03 +0000 (08:46 +0000)]
searchidx: remove_message: pedantic fix for v1
It shouldn't be possible for v1 inboxes to have multiple matches
for a given Message-ID, so the sub would only get called once,
but strange things could happen in 2112 :>
Eric Wong [Fri, 3 Jan 2020 08:46:00 +0000 (08:46 +0000)]
searchidx: add_message: fix and make use of prototypes
Procedural function calls allow prototype checking, and
our add_message prototype was totally wrong to begin with.
Convert most of the "$self->index_*" calls to "index_*($self"
While we're at it, use "//=" to avoid some "unless" statements.
Eric Wong [Fri, 3 Jan 2020 08:45:59 +0000 (08:45 +0000)]
searchidx: split off index_xapian for msg_iter
This ought to save some memory, but it's probably lost in the
noise given the cost of indexing. Regardless it still reduces
the indentation level and makes future changes easier to read.
Eric Wong [Fri, 3 Jan 2020 08:45:58 +0000 (08:45 +0000)]
searchidx: index_diff: allow /^$/ line as diff context
As discovered by solver bug hunting, "git apply" also handles
the case where blank lines w/o leading space are treated as diff
context, apparently because GNU diff once did it: