Eric Wong [Mon, 24 Jun 2019 02:52:52 +0000 (02:52 +0000)]
nntp: send greeting immediately for plain sockets
A tiny write() for the greeting on a just accept()-ed TCP socket
won't fail with EAGAIN, so we can avoid the extra epoll syscall
traffic with plain sockets.
Eric Wong [Mon, 24 Jun 2019 02:52:51 +0000 (02:52 +0000)]
ci: require IO::KQueue on FreeBSD, for now
We'll likely replace IO::KQueue (at least on FreeBSD) using
a pure-Perl syscall()-based version since syscall numbers are
consistent across architectures on FreeBSD and easy to maintain.
IO::KQueue->EV_SET is also shockingly inefficient in that it
calls kqueue() as much as epoll_ctl.
Eric Wong [Mon, 24 Jun 2019 02:52:50 +0000 (02:52 +0000)]
nntp: lazily allocate and stash rbuf
Allocating a per-client buffer up front is unnecessary and
wastes a hash slot. For the majority of (non-malicious)
clients, we won't need to store rbuf in a long-lived object
associated with a client socket at all.
This saves around 10M on 64-bit with 20K connected-but-idle
clients.
Eric Wong [Mon, 24 Jun 2019 02:52:48 +0000 (02:52 +0000)]
nntp: simplify long response logic and fix nesting
We can get rid of the {long_res} field and reuse the write
buffer ordering logic to prevent nesting of responses from
requeue.
On FreeBSD, this fixes a problem of callbacks firing twice
because kqueue as event_step is now our only callback entry
point.
There's a slight change in the stdout "logging" format, in
that we can no longer distinguish between writes blocked
due to slow clients or deferred long responses. Not sure
if this affects anybody parsing logs or not, but preserving
the old format could prove expensive and not worth the
effort.
Eric Wong [Mon, 24 Jun 2019 02:52:47 +0000 (02:52 +0000)]
ds: always use EV_ADD with EV_SET
kqueue EV_ONESHOT semantics are different than epoll
EPOLLONESHOT. epoll only disables watches for that event while
keeping the item in the rbtree for future EPOLL_CTL_MOD. kqueue
removes the watch from the filter set entirely, necessitating
the use of EV_ADD for future modifications.
Eric Wong [Mon, 24 Jun 2019 02:52:46 +0000 (02:52 +0000)]
nntp: reduce allocations for greeting
No need to allocate a new PerlIO::scalar filehandle for every
client, instead we can now pass the same CODE reference which
calls DS->write on a reused string reference.
Eric Wong [Mon, 24 Jun 2019 02:52:44 +0000 (02:52 +0000)]
daemon: use SSL_MODE_RELEASE_BUFFERS
34K per idle connection adds up to large amounts of memory;
especially with the speed of malloc nowadays compared to the
cost of cache misses or worse, swapping.
Eric Wong [Mon, 24 Jun 2019 02:52:43 +0000 (02:52 +0000)]
t/nntpd-tls: slow client connection test
We need to ensure slowly negotiating TLS clients don't block
the event loop. This is why I added the size check of
{wbuf} before and after calling the CODE ref in DS::flush_write.
Eric Wong [Mon, 24 Jun 2019 02:52:42 +0000 (02:52 +0000)]
nntp: call SSL_shutdown in normal cases
This is in accordance with TLS standards and will be needed
to support session caching/reuse in the future. However, we
don't issue shutdown(2) since we know not to inadvertantly
share our sockets with other processes.
Eric Wong [Mon, 24 Jun 2019 02:52:41 +0000 (02:52 +0000)]
ds|nntp: use CORE::close on socket
IO::Socket::SSL will try to re-bless back to the original class
on TLS negotiation failure. Unfortunately, the original class
is 'GLOB', and re-blessing to 'GLOB' takes away all the IO::Handle
methods, because Filehandle/IO are a special case in Perl5.
Anyways, since we already use syswrite() and sysread() as functions
on our socket, we might as well use CORE::close(), as well (and
it plays nicely with tied classes).
Eric Wong [Mon, 24 Jun 2019 02:52:40 +0000 (02:52 +0000)]
daemon: map inherited sockets to well-known schemes
I don't want to specify "--listen" in my systemd .service files,
so map 563 to NNTPS automatically (and 443 to HTTPS, but HTTPS
support doesn't work, yet).
Eric Wong [Mon, 24 Jun 2019 02:52:38 +0000 (02:52 +0000)]
nntp: NNTPS and NNTP+STARTTLS working
It kinda, barely works, and I'm most happy I got it working
without any modifications to the main NNTP::event_step callback
thanks to the DS->write(CODE) support we inherited from
Danga::Socket.
Eric Wong [Mon, 24 Jun 2019 02:52:37 +0000 (02:52 +0000)]
nntp: wait for writability before sending greeting
This will be needed for NNTPS support, since we need
to negotiate the TLS connection before writing the
greeting and we can reuse the existing buffer layer
to enqueue writes.
Eric Wong [Mon, 24 Jun 2019 02:52:36 +0000 (02:52 +0000)]
ds: deal better with FS-related errors IO buffers
Instead of ENOMEM (or fragmentation/swap storms), using tempfile
buffers opens us up to filesystem and storage-related errors
(e.g. ENOSPC, EFBIG, EIO, EROFS). Log these errors, drop the
particular client, and try to limp by with whateve we have left.
Eric Wong [Mon, 24 Jun 2019 02:52:35 +0000 (02:52 +0000)]
allow use of PerlIO layers for filesystem writes
It may make sense to use PerlIO::mmap or PerlIO::scalar for
DS write buffering with IO::Socket::SSL or similar (since we can't
use MSG_MORE), so that means we need to go through buffering
in userspace for the common case; while still being easily
compatible with slow clients.
And it also simplifies GitHTTPBackend slightly.
Maybe it can make sense for HTTP input buffering, too...
Eric Wong [Mon, 24 Jun 2019 02:52:34 +0000 (02:52 +0000)]
nntp: simplify re-arming/requeue logic
We can be smarter about requeuing clients to run and avoid
excessive epoll_ctl calls since we can trust event_step to do
the right thing depending on the state of the client.
Eric Wong [Mon, 24 Jun 2019 02:52:27 +0000 (02:52 +0000)]
ds: favor `delete' over assigning fields to `undef'
This is cleaner in most cases and may allow Perl to reuse memory
from unused fields.
We can do this now that we no longer support Perl 5.8; since
Danga::Socket was written with struct-like pseudo-hash support
in mind, and Perl 5.9+ dropped support for pseudo-hashes over
a decade ago.
Eric Wong [Mon, 24 Jun 2019 02:52:21 +0000 (02:52 +0000)]
ds: remove IO::Poll support (for now)
It may be reinstated at a later time if there's interest; but I
want to be able to use one-shot notifications for certain events
while retaining level-triggered notifications others.
OTOH, I intend to fully support kqueue; via IO::KQueue for now,
but via syscall() eventually to take advantage of the syscall
reduction kevent(2) can provide over (current) epoll APIs.
Eric Wong [Mon, 24 Jun 2019 02:52:20 +0000 (02:52 +0000)]
ds: share watch_chg between watch_read/watch_write
There was much duplicate logic between watch_read and
watch_write. Share that logic, and give us room to enable
edge-triggered or one-shot notifications in the future.
Eric Wong [Mon, 24 Jun 2019 02:52:16 +0000 (02:52 +0000)]
syscall: get rid of unused EPOLL* constants
EPOLLRDBAND is used for DECnet; and I'm pretty sure I won't be
updating any of our code to work with DECnet.
I've never found use for EPOLLHUP or EPOLLERR, either; so
disable those for now and add comments for things I might
actually use: EPOLLET and EPOLLONESHOT.
Eric Wong [Mon, 24 Jun 2019 02:52:15 +0000 (02:52 +0000)]
ds: get rid of redundant and unnecessary POLL* constants
EPOLL* constants already match their POLL* counterparts and
there's no way Linux can ever diverge or change the values
of those constants. So we'll favor the EPOLL* ones since we
use EPOLLEXCLUSIVE, already.
For weird stuff like kqueue, we'd need to keep maintaining
the mapping, anyways.
Eric Wong [Mon, 24 Jun 2019 02:52:08 +0000 (02:52 +0000)]
ds: split out from ->flush_write and ->write
Get rid of the confusing $need_queue variable and all
the associated documentation for it. Instead, make it
obvious that we're either skipping the write buffer or
flushing the write buffer by splitting the sub in two.
Eric Wong [Mon, 24 Jun 2019 02:52:05 +0000 (02:52 +0000)]
AddTimer: avoid clock_gettime for the '0' case
We rely on immediate timers often, so we can avoid the overhead
of an extra subroutine call to retrieve the monotonic time (and
a sometimes-system call on some platforms).
Eric Wong [Sun, 23 Jun 2019 17:42:05 +0000 (17:42 +0000)]
manifest: v2 epoch descriptions based on inbox->description
The default $GIT_DIR/description (provided by git.git templates)
isn't very useful for v2 epochs, so use the inbox description
and suffix it with the epoch number if it's otherwise unnamed.
Requested-by: Konstantin Ryabitsev <konstantin@linuxfoundation.org>
https://public-inbox.org/meta/20190620190017.GA27175@chatter.i7.local/
It never has, AFAIK, but I'm making some changes to this code in
another branch and nearly introduced a bug where it would be
overreading and discarding the pipelined request.
Eric Wong [Sun, 16 Jun 2019 06:11:28 +0000 (06:11 +0000)]
ds: stop distinguishing event read and write callbacks
Having separate read/write callbacks in every class is too
confusing to my easily-confused mind. Instead, give every class
an "event_step" callback which is easier to wrap my head around.
This will make future code to support IO::Socket::SSL-wrapped
sockets easier-to-digest, since SSL_write() can require waiting
on POLLIN events, and SSL_read() can require waiting on POLLOUT
events.
Eric Wong [Sun, 16 Jun 2019 01:04:28 +0000 (01:04 +0000)]
Merge remote-tracking branch 'origin/newspeak' into xcpdb
* origin/newspeak:
comments: replace "partition" with "shard"
t/xcpdb-reshard: use 'shard' term in local variables
xapcmd: favor 'shard' over 'part' in local variables
search: use "shard" for local variable
v2writable: use "epoch" consistently when referring to git repos
adminedit: "part" => "shard" for local variables
v2writable: rename local vars to match Xapian terminology
v2writable: avoid "part" in internal subs and fields
search*: rename {partition} => {shard}
xapcmd: update comments referencing "partitions"
v2: rename SearchIdxPart => SearchIdxShard
inboxwritable: s/partitions/shards/ in local var
tests: change messages to use "shard" instead of partition
v2writable: rename {partitions} field to {shards}
v2writable: count_partitions => count_shards
searchidxpart: start using "shard" in user-visible places
rename reference to git epochs as "partitions"
admin|xapcmd: user-facing messages say "shard"
v2writable: update comments regarding xcpdb --reshard
doc: rename our Xapian "partitions" to "shards"
Eric Wong [Sat, 15 Jun 2019 17:38:42 +0000 (17:38 +0000)]
Merge remote-tracking branch 'origin/ds'
* origin/ds:
ds: stop caring about event flags set by epoll/poll/kqueue
ds: do not distinguish between POLLHUP and POLLERR
ds: remove read method, here, too
nntp: use sysread to append to existing buffer
ds: remove steal_socket method
ds: remove {fd} field
ds: reduce Errno imports and drop ->close reason
ds: cleanup Errno imports and favor constant comparisons
ds: simplify write buffer accounting
Eric Wong [Fri, 14 Jun 2019 10:09:13 +0000 (10:09 +0000)]
t/git-http-backend: explain purpose of test
I found myself tempted to switch to HTTP::Tiny, here, since
it's distributed with Perl since 5.14, unlike Net::HTTP
(which AFAIK was never a part of Perl proper).
But we really want to use Net::HTTP, here, since it's
lower-level and allows us to trigger server-side buffering
by not reading the entity body.
PublicInbox::Inbox objects have minimal dependencies, so
drop code to support old tests which existed before the
PublicInbox::Inbox object came into existence.
Eric Wong [Fri, 14 Jun 2019 16:42:26 +0000 (16:42 +0000)]
t/www_listing: favor HTTP::Tiny over Net::HTTP
More testers are likely to have HTTP::Tiny than Net::HTTP, since
HTTP::Tiny is a dual-life module and distributed with Perl since
Perl 5.14 (2011-05-14), whereas Net::HTTP will likely live in
a separate package forever.
Eric Wong [Fri, 14 Jun 2019 16:25:39 +0000 (16:25 +0000)]
Merge remote-tracking branch 'origin/reshard' into next
* origin/reshard:
xcpdb: support resharding v2 repos
xcpdb: use destination shard as progress prefix
xapcmd: preserve indexlevel based on the destination
v2writable: use a smaller default for Xapian partitions
Eric Wong [Fri, 14 Jun 2019 16:23:13 +0000 (16:23 +0000)]
Merge remote-tracking branch 'origin/manifest' into next
* origin/manifest:
git: ensure ->modified returns an integer
www: support $INBOX/git/$EPOCH.git for v2 cloning
www: wire up /$INBOX/manifest.js.gz, too
wwwlisting: generate grokmirror-compatible manifest.js.gz
wwwlisting: allow hiding entries from manifest
Eric Wong [Thu, 13 Jun 2019 00:29:37 +0000 (00:29 +0000)]
xcpdb: support resharding v2 repos
v2 repos are sometimes created on machines where CPU
parallelization exceeds the capability of the storage devices.
In that case, users may reshard the Xapian DB to any smaller,
positive integer to avoid excessive overhead and contention when
bottlenecked by slow storage.
Resharding can also be used to increase shard count after
hardware upgrades.
Eric Wong [Wed, 12 Jun 2019 00:35:32 +0000 (00:35 +0000)]
v2writable: use a smaller default for Xapian partitions
Apparently 16 CPUs (probably HT) and SATA storage is common
these days. Having excessive Xapian partitions leads to
contention and excessive FD/space use. So set a smaller
default but continue allowing user-specified values to bump
this up.
Eric Wong [Thu, 13 Jun 2019 08:10:02 +0000 (08:10 +0000)]
git: remove cat_file sub callback interface
We weren't using it, and in retrospect, it makes no sense to use
this API cat_file for giant responses which can't read quickly
with minimal context-switching (or sanely fit into memory for
Email::Simple/Email::MIME).
For giant blobs which we don't want slurped in memory, we'll
spawn a short-lived git-cat-file process like we do in ViewVCS.
Otherwise, monopolizing a git-cat-file process for a giant
blob is harmful to other PSGI/NNTP users.
A better interface is coming which will be more suitable for
for batch processing of "small" objects such as commits and
email blobs.
Eric Wong [Fri, 14 Jun 2019 00:27:31 +0000 (00:27 +0000)]
nntp: filter out duplicate Message-IDs for leafnode
It's the unfortunate reality that there are some clients which
reuse Message-IDs (in which we generate + use another) or set
multiple Message-IDs on their own. While the v2 format
addresses that, NNTP clients such as leafnode are not always
prepared to deal with that case.
So, ensure NNTP clients only see a single Message-ID, and
show the others as 'X-Alt-Message-ID'.
Eric Wong [Thu, 13 Jun 2019 20:46:52 +0000 (20:46 +0000)]
nntp: ensure Message-ID is not folded for leafnode
Leafnode cannot handle Message-ID headers which are too long and
require folding via Email::Simple::Header. Since there are
already many of these messages in git with the header already
folded, we need to handle the unfolding when emitting the
message via NNTP.
As far as we know, Leafnode is the only client software
incapable of handling this case.