The sendfile() implementation for evbuffer_add_file is potentially more
efficient, but it has a problem: you can only use it to send bytes over
a socket using sendfile(). If you are writing bytes via SSL_send() or
via a filter, or if you need to be able to inspect your buffer, it
doesn't work.
As an easy fix, this patch disables the sendfile-based implementation of
evbuffer_add_file on an evbuffer unless the user sets a new
EVBUFFER_FLAG_DRAINS_TO_FD flag on that evbuffer, indicating that the
evbuffer will not be inspected, but only written out via
evbuffer_write(), evbuffer_write_atmost(), or drained with stuff like
evbuffer_drain() or evbuffer_add_buffer(). This flag is off by
default, except for evbuffers used for output on bufferevent_socket.
In the future, it could be interesting to make a best-effort file
segment implementation that tries to send via sendfile, but mmaps on
demand. That's too much complexity for a stable release series, though.
- Prevent evbuffer_{add,prepend}_buffer from moving read-pinned chains.
- Fix evbuffer_drain to handle read-pinned chains better.
- Raise the limit on WSABUFs from two to MAX_WSABUFS for overlapped reads.
To implement evbuffer_expand() properly, you need to be able to
replace the last chunk that has data, which means that we need to keep
track of the the next pointer pointing to the last_with_data chunk,
not the last_with_data chunk itself.
This constant decides the smallest (and typical) size of each evbuffer
chain. Since this number includes sizeof(evbuffer_chain) overhead,
the old value (256) was just too low: on 64-bit platforms, it would
spend nearly 20% of the allocations on overhead. The new values mean
that we'll be spending closer to 5% of evbuffer allocations on overhead.
It would be nice to get this number even lower if we can.
This actually makes some of the code a lot simpler. The only
ones that actually used previous_to_last for anything were reserving
and committing space.
This is the first patch in a series to replace previous_to_last with
last_with_data. Currently, we can only use two partially empty chains
at the end of an evbuffer, so if we have one with 511 bytes free, and
another with 512 bytes free, and we try to do a 1024 byte read, we
can't just stick another chain on the end: we need to reallocate the
last one. That's stupid and inefficient.
Instead, this patch adds a last_with_data pointer to eventually
replace previous_to_last. Instead of pointing to the penultimated
chain (if any) as previous_to_last does, last_with_data points to the
last chain that has any data in it, if any. If all chains are empty,
last_with_data points to the first chain. If there are no chains,
last_with_data is NULL.
The next step is to start using last_with_data everywhere that we
currently use previous_to_last. When that's done, we can remove
previous_to_last and the code that maintains it.
There were a couple of places in the code where we manually kept lock
counts to make sure we never accessed resources without holding a
lock, and that we never released a lock we didn't have. The
lock-debugging code already puts counts on _every_ lock when lock
debugging is enabled, so there is no need to keep these counts around
otherwise. This patch rewrites the ASSERT_FOO_LOCKED macros to all
use a common EVLOCK_ASSERT_LOCKED().
We also teach the lock debugging code to keep track of who exactly
holds each lock, so that EVLOCK_ASSERT_LOCKED() means "locked by this
thread."
Previously, our default lock model kind of assumed that every lock was
potentially a read-write lock. This was a poor choice, since
read-write locks are far more expensive than regular locks, and so the
lock API should only use them when we can actually take advantage of
them. Neither our pthreads or win32 lock implementation provided rw
locks.
Now that we have a way (not currently used!) to indicate that we
really want a read-write lock, we shouldn't actually say "lock this
for reading" or "lock this for writing" unless we mean it.
This patch from Chris Davis saves some callback depth, and adds proper
ref-counting to bufferevents when there's a deferred evbuffer callback
inflight. It could use a couple more comments to really nail down what
its invariants are.
svn:r1543
From the documentation:
Prevent calls that modify an evbuffer from succeeding. A buffer may
frozen at the front, at the back, or at both the front and the back.
If the front of a buffer is frozen, operations that drain data from
the front of the buffer, or that prepend data to the buffer, will
fail until it is unfrozen. If the back a buffer is frozen, operations
that append data from the buffer will fail until it is unfrozen.
We'll use this to ensure correctness on an evbuffer when we're waiting
for an overlapped IO call to finish.
svn:r1143
For overlapped IO (and possibly other stuff) we need to be able to
label an evbuffer_chain as "pinned", meaning that every byte in it
must remain at the same address as it is now until it unpinned. This
differs from being "immutable": it is okay to add data to the end
of a pinned chain, so long as existing data is not moved.
svn:r1142
a) this is 2009
b) niels and nick have been comaintainers for a while
c) saying "all rights reserved" when you then go on to explicitly
disclaim some rights is sheer cargo-cultism.
svn:r1065
For now, there is just one: enabled. This lets us avoid lots of
mallocs/frees/tailq-manipulations just to turn a callback on and off.
The revised bufferevent code wants this.
svn:r1047
fragmentation in evbuffer_expand by increasing the size of the last buffer
in the chain; as a result with have to keep track of the previous_to_last
chain; provide a evbuffer_validate() function in the regression test to
make sure that all evbuffer are internally consistent.
svn:r699