phk [Sat, 23 Feb 2008 20:36:33 +0000 (20:36 +0000)]
The expiry module keeps all cached objects on two data structures:
the LRU list and the binary heap. In both of these cases, operations
on one object will result in certain fields in neighbor objects in
these data structures to be updated.
In difference from cache_hash.c which examine objects related by
hash match where the existence of the hash lookup in the first place
is a predictor for their likely use, in cache_expire the neighbor
objects are totally unrelated and the fact that we update their
list pointers or binheap index in no way indicates that they will
get a cache hit any time soon.
Paging in one page for a number of objects, just to move another
object up or down the binheap or LRU list is thus not only slow,
but also increases varnish' VM footprint for no real benefit.
This commit moves the relevant housekeeping fields into a "objexp"
structure, which gets hung off the objects when they enter the cache.
The objexp structure is small (40 bytes on i386) so statistically it
is more than an order of magnitude more likely to already be in core
when we need it, compared to the object itself.
phk [Sat, 23 Feb 2008 19:54:44 +0000 (19:54 +0000)]
Only move objects to the tail of the LRU queue if we can get the
expiry mutex without waiting.
This is in addition to the already present "only if it have not
been moved recently" check.
This additional mutex-contestion reduction obviously might leave
the LRU list badly out of order, but this can be worked around
by examining obj.last_use in vcl_discard()
des [Thu, 21 Feb 2008 21:14:57 +0000 (21:14 +0000)]
We don't need cryptographic-strength randomness here. Try /dev/urandom
first, then /dev/random, then fall back to pid and time. Using an
uninitialized stack variable as seed is just silly, and Coverity rightly
complains about it (CID#19)
des [Tue, 19 Feb 2008 11:57:04 +0000 (11:57 +0000)]
If HSH_Lookup() returns non-NULL, assert that sp->objhead != NULL.
HSH_Lookup() is supposed to guarantee this, but it appears that it
sometimes doesn't (perhaps a bug snuck in with grace mode?)
phk [Tue, 19 Feb 2008 11:10:12 +0000 (11:10 +0000)]
Revise the kqueue_acceptor with a sledgehammer.
Use EV_ONESHOT for all session events to make the kernel delete the
event when it fires, to remove any chance of any race with session
state and kqueue event arming.
For sessions with acceptfilter, this does just what we want (and I
kick myself for not realizing this much sooner).
For sessions where the acceptfilter is not enabled or has given up,
this results in an extra kevent arming operation for each read, but
this is still a much lower overhead than synchrnously deleting
the event when before passing the session on.
Delete all the workarounds and band-aids that had accumulated.
phk [Mon, 18 Feb 2008 12:00:19 +0000 (12:00 +0000)]
Uncapitalize DIAGNOSTICS, since diag_bitmap is not related to the
#ifdef, which we retain for really heavy duty instrumentation, should
we ever need that.
phk [Mon, 18 Feb 2008 11:47:55 +0000 (11:47 +0000)]
Move the logging of state engine states to use the diag_bitmap
instead of #ifdef DIAGNOSTICS for control.
Also reduce VSL mutex cost by 50% for the common case where we have
a worker thread: We did a WSL_Flush() followed by a VSL(), doing a
WSL() before the WSL_FLush saves one VSL mutex op.
phk [Mon, 18 Feb 2008 11:45:58 +0000 (11:45 +0000)]
Make a parameter "diag_bitflag" which can control deeper diagnostics for
us, instead of the #ifdef DIAGNOSTICS which is always not there when you
need it or there when you don't want it.
phk [Fri, 15 Feb 2008 08:54:20 +0000 (08:54 +0000)]
Determine our backend (using the director) before we filter the req
into the bereq, in order to be able to assign a default Host: header
if there is none.
des [Wed, 13 Feb 2008 13:05:36 +0000 (13:05 +0000)]
Some source files (especially in libraries) have embedded test
programs. Add a configure option and a corresponding automake
conditional to enable these tests.
des [Mon, 11 Feb 2008 10:46:09 +0000 (10:46 +0000)]
Update backend declaration syntax. Note that a) vcl.7 needs a partial
rewrite to track this change, and b) there have been other changes which
also need to be merged in.
phk [Thu, 7 Feb 2008 09:52:26 +0000 (09:52 +0000)]
Remove ident string from directors, they are not recycled.
Add vcl_name to backend hosts. Simple backends get the obvious
name. Directors inlined backend hosts gets the directors name
with an array suffix, for instance "b1[1]".
phk [Wed, 6 Feb 2008 15:19:49 +0000 (15:19 +0000)]
First part of major backend overhaul.
*** Please do not use -trunk in production until I say so again ***
I have not entirely decided in the precise terminology, so the following
may sound a lot more complicated than it really is:
In VCL we can now have "backends" and "directors" both of which we
treat as a "backend".
When we define backends and directors in VCL, they refer to "backend
hosts" which is just another way to say "hostname+portname" but later
these will grow other parameters (max connections etc).
A director is a piece of code that selects a "backend host" somehow,
"random" and "round-robin" are the first algorithms. A backend
can still be specified directly of course, that's the "simple director"
that always return the same "backend host".
This is probably where an example is in order:
/* A backend as we know it */
backend b1 {
.host = "fs";
.port = "80";
}
/* A director */
director b2 random {
{
/* We can refer to named backends */
.backend = b1;
.weight = 7;
}
{
/* Or define them inline */
.backend = {
.host = "fs2";
}
.weight = 3;
}
}
sub vcl_recv {
if (req.url ~ "\[[a-z]]") {
set req.backend = b2;
} else {
set req.backend = b1;
}
}
This results in quite a lot of changes in the C code, VRT API and
VCL compiler, the major thrust being:
Directors like "simple" and "random" will not have to think about
the actual connections to the backends, but just concentrate on
selecting which backend should be used.
When a new VCL is loaded, it will instantiate all directors, but
try to reuse any preexisting "backend hosts" (which we still
call "backend" in the C code).
This is simple for a backend like "b1" in the example above, but
sligthly more complex for the backend inlined in b2. The VCL
compiler solves this, by qualifying the ident string for the inlined
backend host with the prefix "b2 random :: 2 :: ", so that a reload
of the same director with the same (unchanged) inline backend host
will match, but none other will.
One implication of instantiating all directors for every VCL load,
is that private statistics cannot be reused, but stats on the
backend host can. This is likely a very fine point of no consequence.
Once the backend is selected by the director, the generic code in
cache_backend.c will cope with reusing the connection pool,
establishing connections and all that, moving most of the nastyness
out of directors, leaving cache_dir_simple.c with only 96 lines of
code, of which the license is a large fraction.
Until now, we have done automatic DNS re-lookups, but they seem to
cause more grief than advantage (I suspect some of the DNS lookups
to be resposible for long timeouts), so that will be dropped, and
instead we might add an explicit CLI command for this later.
The code as here committed can handle a couple of simple requests,
but there are a large number of INCOMPL()'s that need to be resolved
before this is ready for prime time again.