diff -Naur apache_1.3.6+01-07/conf/httpd.conf-dist apache_1.3.6+01-08/conf/httpd.conf-dist
--- apache_1.3.6+01-07/conf/httpd.conf-dist Tue Jul 20 22:19:58 1999
+++ apache_1.3.6+01-08/conf/httpd.conf-dist Thu Sep 2 10:12:04 1999
@@ -210,6 +210,16 @@
#
#ExtendedStatus On
+#
+# QSC: Enable the Quick Shortcut Cache. The QSC caches response
+# headers and data together for very fast response to requests for
+# static content. It is tightly integrated with and requires the
+# mmap_static module.
+#
+
<IfModule mod_mmap_static.c> QSC on </IfModule> else QSC off+This directive enables or disables the Quick Shortcut Cache. +
+
+ Use of this module allows use of the Quick Shortcut (or Static-content) + Cache (QSC) for very fast static-content serving. + See the QSC documentation for details. +
+This is an experimental module and should be used with diff -Naur apache_1.3.6+01-07/htdocs/manual/mod/mod_status.html apache_1.3.6+01-08/htdocs/manual/mod/mod_status.html --- apache_1.3.6+01-07/htdocs/manual/mod/mod_status.html Mon Mar 22 16:17:41 1999 +++ apache_1.3.6+01-08/htdocs/manual/mod/mod_status.html Thu Sep 2 10:13:26 1999 @@ -47,6 +47,8 @@
+
++
+Mike Abbott - mja@sgi.com
++Apache/1.3.X and beyond support a very fast cache of static content and +HTTP response headers known as the Quick Shortcut (or Static-content) +Cache, or QSC. The QSC is meant for sites that serve lots of data as-is +from disk, such as images, unparsed HTML, and plain text. Sites that +serve mostly dynamically-generated content, such as CGI output or +on-disk content with headers or footers generated on the fly, probably +should not use the QSC.
++Normally Apache processes an HTTP request by following a long list of rules, such as converting the URI to a +file name, authenticating the request, generating HTTP headers for the +response, sending the response, and logging information about the +transaction. Apache performs all these steps (more or less) for every +request, even if it has handled the same request previously. This +memory-less behavior is required for steps such as authentication but +is unnecessary for URI-to-file translation and HTTP response header +generation when the response consists of static content. The QSC adds +memory to Apache, allowing it to shortcut the processing of +previously-seen requests for static content.
++After Apache reads an HTTP request and locates the appropriate virtual host context in which to handle +the request, it checks whether the QSC can respond to the request -- +whether the request is cachable and whether the +URI and virtual host match a cached entry. If so, the QSC bypasses all +unnecessary processing and sends the previously-generated HTTP response +quickly, then Apache logs the transaction and moves on to the next +request.
++When the QSC cannot respond quickly, Apache continues processing the +request normally. When such normal processing results in the mmap_static module sending the +HTTP response, that module tries to insert the request and response +into the QSC -- which succeeds only if the request and response are cachable and the cache isn't full. +Finally, as with the cached response, Apache logs the transaction and +moves on to the next request. Note that the QSC caches both the +response headers and the response body.
++Only the mmap_static module inserts entries into the QSC, for a number +of reasons:
++When looking for a cache entry to satisfy a request, the QSC matches +the virtual host as well as the URI because different virtual hosts can +map the same URI to different files.
+
+Each QSC entry contains two nearly identical sets of HTTP response
+headers, one for keep-alive connections (the headers contain a Connection:
+keep-alive header) and one for non-keep-alive connections (the
+headers contain a Connection: close header). Caching both
+versions allows the QSC to respond quickly regardless of the nature of
+the connection and without having to generate the HTTP headers for each
+request -- a key ingredient for quick response.
+Furthermore, the QSC aligns both sets of response headers on a certain
+memory boundary and pads them out to a certain length. Generally this
+alignment is the secondary cache line size of the system on which
+Apache runs. When asked to send data out on a network, operating
+systems typically align misaligned data by copying it. The QSC
+pre-aligns the headers (and the mmap_static module automatically aligns
+the body due to the nature of memory-mapping files) and pads the
+headers (by adding spaces to the Server header value) to
+eliminate this overhead. You can adjust or disable the
+header alignment manually.
+This section describes how to compile and enable QSC support in your +Apache server.
++The QSC requires the mmap_static +module. In the standard Apache distribution neither the QSC nor the +mmap_static module are compiled into the server. You must add them both +to the compilation configuration to use the QSC:
++ $ CFLAGS=-DUSE_QSC configure --enable-module=mmap_static + $ make ++
+(The QSC is an enhancement to core Apache, while mmap_static is an +Apache module.) There are also advanced +options to controlling QSC behavior, described below.
+
+In addition, a run-time configuration directive, QSC, enables and disables
+the QSC. By default the QSC is off (disabled)
+but this snippet from the standard httpd.conf file enables it when the
+mmap_static module is also compiled into the server:
+ <IfModule mod_mmap_static.c> + QSC on + </IfModule> ++
+In other words, compiling both the QSC and the mmap_static module
+automatically enables the QSC. The QSC directive exists to
+allow you to disable it.
+You must also configure the mmap_static module by adding an mmapfile directive for +each file you want cached.
++Once configured the QSC will operate automatically.
+
+All of the data the QSC stores is in shared memory (memory accessible
+to all of Apache's subprocesses) so that the cache is not duplicated
+for each Apache child process. Systems that do not support anonymous
+shared memory (that define neither HAVE_MMAP nor HAVE_SHMGET)
+cannot use the QSC.
+The QSC requires one piece of functionality that is completely new to
+Apache and so has not had the benefit of years of multi-platform
+porting: a way to compare and swap (cas) two values atomically
+(i.e., in a thread-safe manner). All of the QSC's internal data
+structures are stored in shared memory so every update to that data
+must be done in a way that is guaranteed to be safe and correct for all
+the child processes. If your attempt to compile the QSC fails with the
+error "need atomic compare-and-swap function," you must port
+the function qsc_cas() to your system.
+The QSC gathers statistics about its operation. You can view these +statistics on the page that the status +module generates in response to requests of the form:
++ http://your.server.name/server-status ++
+This section has examples and explanations of this information.
++This is what the status page looks like when the QSC is disabled:
++ Quick Shortcut Cache (QSC) Status: + QSC disabled ++
+There may be an explanation why the QSC is disabled in the server's +error log. The next example shows the statistics from a freshly-started +server with the QSC enabled:
++ Quick Shortcut Cache (QSC) Status: + hit ratio 0/1 (0.00%) + uncachable 1/1 (100.00%) + uncachable misses 1/1 (100.00%) + uncachable requests 0/1 (0.00%) + uncachable responses 0/1 (0.00%) + resets 1 + Hash table + failed insertions 0 + entries 0 + duplicate entries 0 + bucket use 0/32768 (0.00%) + hash effectiveness 0/0 (0.00%) + longest chain 0 + avg. chain 0.0 + avg. nonempty chain 0.0 + Chain length histogram: + 1 2 3 4 5+ + 0 0 0 0 0 + Memory use (in bytes) + table + misc 131104 + entries 0 + URIs 0 + headers 0 + total 135264/5000000 (2.71%) + mapped file data 0 + mapped file vaddrs 0 (0 16384-byte pages) ++
+It's pretty clear that the cache is empty at this point. The next +example shows the statistics from the same server after running for a +while:
++ Quick Shortcut Cache (QSC) Status: + hit ratio 2104749/2112853 (99.62%) + uncachable 40/2112853 (0.00%) + uncachable misses 40/8104 (0.49%) + uncachable requests 0/2112853 (0.00%) + uncachable responses 0/2112853 (0.00%) + resets 1 + Hash table + failed insertions 0 + entries 8064 + duplicate entries 0 + bucket use 7923/32768 (24.18%) + hash effectiveness 7923/8064 (98.25%) + longest chain 2 + avg. chain 0.2 + avg. nonempty chain 1.0 + Chain length histogram: + 1 2 3 4 5+ + 7782 141 0 0 0 + Memory use (in bytes) + table + misc 131104 + entries 322560 + URIs 246024 + headers 4128768 + total 4844640/5000000 (96.89%) + mapped file data 1146761280 + mapped file vaddrs 1229455360 (75040 16384-byte pages) ++
+The QSC computes some of the statistics (such as the hash chain
+lengths, histogram, and memory use) only when requested, and computing
+them frequently may interfere with normal server operation. You can
+view a condensed statistics page that skips the computation by
+appending ?qsc=quick to your request, like this:
+ http://your.server.name/server-status?qsc=quick ++
+which produces this output:
++ Quick Shortcut Cache (QSC) Status: + hit ratio 2104749/2112854 (99.62%) + uncachable requests 0/2112854 (0.00%) + uncachable responses 0/2112854 (0.00%) + resets 1 + Hash table + failed insertions 0 ++
+Alternatively, you can view detailed QSC information by appending ?qsc=full,
+like this:
+ http://your.server.name/server-status?qsc=full ++
+which produces this output (with a large portion omitted for brevity):
++ Quick Shortcut Cache (QSC) Status: + hit ratio 2104749/2112855 (99.62%) + uncachable 42/2112855 (0.00%) + uncachable misses 42/8106 (0.52%) + uncachable requests 0/2112855 (0.00%) + uncachable responses 0/2112855 (0.00%) + resets 1 + Hash table + failed insertions 0 + entries 8064 + duplicate entries 0 + bucket use 7923/32768 (24.18%) + hash effectiveness 7923/8064 (98.25%) + longest chain 2 + avg. chain 0.2 + avg. nonempty chain 1.0 + Chain length histogram: + 1 2 3 4 5+ + 7782 141 0 0 0 + Memory use (in bytes) + table + misc 131104 + entries 322560 + URIs 246024 + headers 4128768 + total 4844640/5000000 (96.89%) + mapped file data 1146761280 + mapped file vaddrs 1229455360 (75040 16384-byte pages) + Full entry info + server * URI @ hash-bucket -> keep-alive-header-bytes;non-keep-alive-header-bytes + body-bytes file-name + main * /spec/file_set/dir115/class0_0 @ 37 -> 256;256 + 102 /a/htdocs/spec/file_set/dir115/class0_0 + main * /spec/file_set/dir115/class0_1 @ 38 -> 256;256 + 204 /a/htdocs/spec/file_set/dir115/class0_1 + main * /spec/file_set/dir115/class0_2 @ 39 -> 256;256 + 306 /a/htdocs/spec/file_set/dir115/class0_2 + main * /spec/file_set/dir115/class0_3 @ 40 -> 256;256 + 408 /a/htdocs/spec/file_set/dir115/class0_3 + ... thousands of lines elided for brevity ... + main * /spec/file_set/dir214/class3_8 @ 32752 -> 256;256 + 921600 /a/htdocs/spec/file_set/dir214/class3_8 ++
+This section explains the final example above in great detail.
++ hit ratio 2104749/2112855 (99.62%) ++
+The hit ratio is the ratio of the number of requests +successfully served by the QSC to the total number of requests made to +the server. The number in parentheses is the ratio expressed as a +percentage. In this case there were 2,112,855 total requests, 2,104,749 +or 99.62% of which were cache hits -- the QSC responded to the requests +quickly -- and 8,106 or 0.38% were cache misses -- Apache processed the +requests without assistance from the QSC.
++ uncachable 42/2112855 (0.00%) + uncachable misses 42/8106 (0.52%) + uncachable requests 0/2112855 (0.00%) + uncachable responses 0/2112855 (0.00%) ++
+These explain the cache misses. Of the 2,112,855 total requests, 42 +were uncachable meaning that not only did they miss (were not +in) the cache but also the QSC could not enter them into its cache for +some reason. In this case, all 42 uncachable requests were uncachable +misses meaning some handler other than the mmap_static module's +handled the request. For instance, all server-status requests are +handled by the status module and so are uncachable misses. (You can see +the number of uncachable misses increasing by one for each example +above.) Other reasons requests may be uncachable are uncachable +requests and uncachable responses.
++The QSC caches responses to HTTP requests only +when both the request and the response meet certain criteria. To be +cachable a request must:
+r->no_cache
+ == 0), and
+ +and its response must:
+r->no_cache
+ == 0), and
+
+For example, pressing the "Reload" button on some popular
+browsers causes them to issue requests with a Pragma: no-cache
+ and/or Cache-control header which are meant to bypass
+caching mechanisms such as the QSC.
+ resets 1 ++
+The QSC counts the number of times it has been reset. The counter +starts at zero but Apache's normal startup procedures cause one reset. +Each time the server is restarted the QSC clears its cache completely, +zeros-out all the statistics except this counter, and increments this +counter. Thus, the statistics displayed are since the last reset, not +since the server was started.
++ Hash table + failed insertions 0 ++
+This is the number of times the QSC tried to insert a new entry into +its cache and failed. Failure can occur when, for example, the QSC has +consumed all the memory it is allowed to use (i.e., the cache is full). +If you see a large number of failed insertions, consider increasing +your QSC's cache size.
++ entries 8064 + duplicate entries 0 ++
+This shows you how many entries are in the cache, and how many of those +entries are duplicates of one another. Duplicate entries are harmless +aside from wasting a little memory.
++ bucket use 7923/32768 (24.18%) + hash effectiveness 7923/8064 (98.25%) + longest chain 2 + avg. chain 0.2 + avg. nonempty chain 1.0 + Chain length histogram: + 1 2 3 4 5+ + 7782 141 0 0 0 ++
+The above information describes the effectiveness of the QSC's hash +algorithm. This particular instance has 32,768 cache buckets of which +7,923 or 24.18% have at least one entry (the rest are empty). The +effectiveness of the hash function is the ratio of the number of +buckets over which entries are spread to the number of entries, in this +case 7,923 to 8,064 or 98.25% effective. Higher effectiveness means +shorter hash chains which are faster when looking up entries. The +longest hash chain has only two entries which is very good. If your +server shows a low hash efficiency and long hash chains, consider +increasing your QSC's number of hash buckets. The +average (arithmetic mean) chain length is just 0.2 entries per bucket, +including empty buckets, and the average chain length of non-empty +buckets is 1.0 which is excellent. The histogram displays the number of +hash buckets having chains with one, two, three, four, and five-or-more +entries. You can control the number of histogram bins.
++ Memory use (in bytes) + table + misc 131104 ++
+The QSC carefully manages the amount of memory it uses and this part of +the report explains where all the bytes are going. This line accounts +for the empty hash table -- the size of which is directly related to +the number of hash buckets -- and other data structures necessary for +the QSC's operation such as the statistics counters. In this example +there are 32,768 hash buckets each of which is four bytes in size so +the whole table consumes 131,072 bytes. The remaining 32 bytes (for a +total of 131,104) are for the statistics counters and other overhead.
++ entries 322560 ++
+This line accounts for the memory used for the hash entry data +structures. In this example each entry consumes 40 bytes and there are +8,064 of them for a total of 322,560 bytes.
++ URIs 246024 ++
+Each hash entry maps a URI and virtual host to HTTP response headers +and data. This counts the amount of memory consumed by remembering +those URIs. The average cached URI length in this example is 246,024 +bytes divided by 8,064 entries or about 31 bytes.
++ headers 4128768 ++
+This is the number of bytes consumed by remembering the HTTP response +headers for each cached entry. This is approximately double the number +of bytes of header information sent in response to a cached entry +because the QSC keeps two sets of headers, +one for keep-alive connections and one for non-keep-alive connections. +The average number of bytes of cached headers is 4,128,768 bytes +divided by 8,064 entries or exactly 512 bytes (two sets of 256-byte +headers per entry). This number is so tidy because of header +padding and alignment.
++ total 4844640/5000000 (96.89%) ++
+This line displays the total amount of memory that the QSC is using and +the maximum amount to which it limits itself. In this case the cache is +pretty close to full. You can control the maximum +cache size.
++ mapped file data 1146761280 + mapped file vaddrs 1229455360 (75040 16384-byte pages) ++
+The QSC itself manages only the hash table, the URI strings, and the +headers. The mmap_static module manages the cache of memory-mapped file +contents. These two lines count the number of bytes of response body +data (in this case 1,146,761,280 bytes for an average file size of +142,208 bytes) and the number of bytes of virtual memory consumed +(1,229,455,360 bytes). The latter is larger because memory-mapping a +file whose size is not an exact multiple of the machine's page size +wastes the space between the end of the file and the end of the page. +In this case the machine's page size is 16 KB and 75,040 pages are used +to map the file contents.
++ Full entry info + server * URI @ hash-bucket -> keep-alive-header-bytes;non-keep-alive-header-bytes + body-bytes file-name + main * /spec/file_set/dir115/class0_0 @ 37 -> 256;256 + 102 /a/htdocs/spec/file_set/dir115/class0_0 + main * /spec/file_set/dir115/class0_1 @ 38 -> 256;256 + 204 /a/htdocs/spec/file_set/dir115/class0_1 + main * /spec/file_set/dir115/class0_2 @ 39 -> 256;256 + 306 /a/htdocs/spec/file_set/dir115/class0_2 + main * /spec/file_set/dir115/class0_3 @ 40 -> 256;256 + 408 /a/htdocs/spec/file_set/dir115/class0_3 + ... thousands of lines elided for brevity ... + main * /spec/file_set/dir214/class3_8 @ 32752 -> 256;256 + 921600 /a/htdocs/spec/file_set/dir214/class3_8 ++
+This final section, available using the ?qsc=full
+ server-status extension, lists all of the information known about each
+cache entry. There were as many lines as there are cache entries so
+most of them were omitted for brevity. The following information is
+printed for each entry, as the list's header notes:
| server | +The file name and line number where the virtual server was
+ defined (for lack of better virtual host identification), or main
+ for the main server. |
+
| URI | +The URI for which the response is cached. | +
| hash-bucket | +The ordinal of the bucket into which the URI hashes. | +
| keep-alive-header-bytes | +The number of bytes of HTTP response header cached for a + keep-alive response. | +
| non-keep-alive-header-bytes | +The number of bytes of HTTP response header cached for a + non-keep-alive (i.e., Connection: close) response. | +
| body-bytes | +The number of bytes of HTTP response body. | +
| file-name | +The name of the cached file, available only when the QSC is
+ compiled with QSC_DEBUG enabled. Without QSC_DEBUG
+ n/a is displayed ("not available"). |
+
+All of the following are compile-time options. The first two must be +defined manually. The rest are defined in the QSC source code.
+USE_QSC |
+ + Compiles the QSC into Apache. + Default:USE_QSC is not defined so the QSC is
+ disabled. |
+
QSC_DEBUG |
+ + Enables internal consistency checks. ++ Makes the QSC keep track of the name of the file mapped by the + mmap_static module for each entry. The file name is displayed on the full status page. + Default:QSC_DEBUG is not defined so debugging
+ is disabled. |
+
QSC_HIST_SIZE |
+ + Sets the number of hash bucket histogram bins the status page displays. + Default: 5. |
+
QSC_MAX_SIZE |
+ + Sets the maximum number of bytes of memory the QSC will consume. Note + that this does not include mapped file data. + Default: 4194304 (4 MB). |
+
QSC_HASH_SIZE |
+ + Sets the number of hash buckets. + Default: 128. |
+
QSC_HEADER_GRAIN |
+ + Sets both the virtual address alignment boundary of cached HTTP + response headers and the number of bytes to which the headers are + padded. For best performance make this equal to the size of the largest + cache line size on the system on which Apache runs. Must be a power of + two. The special value 0 disables alignment and padding. + Default: system dependent (typically 32 or 128). |
+
QSC_GRAIN |
+
+ Sets both the virtual address alignment boundary of internal memory
+ allocations and the number of bytes to which the allocations are
+ padded. Must be a power of two at least as large as the larger of a
+ pointer and a long. Same idea as |
+
QSC_MAX_ALLOC |
+ + Sets the maximum single-allocation size in bytes. Internal memory + allocations larger than this will fail and the request/response will + not be cached. + Default: 512. |
+
QSC_RED_ZONE |
+
+ Sets the number of bytes of safety margin required between the two
+ internal memory allocation zones. Should be a small multiple of |
+
+Apache API, mmap_static module, status module, virtual hosts
+Quick Shortcut Cache (QSC) Status:\n", r);
+
+ if (qsc) {
+ static const char fmt[] = " %-20s %s\n";
+ char buf[128];
+ struct qsc_stats stats;
+ int i, full, quick, nbuckets, nentries, longest_chain, ndupent;
+ ap_atomic nlookups, nuribytes, nheaderbytes, nbodybytes, nbodyvas;
+ int histogram[QSC_HIST_SIZE], pagesize;
+ struct qsc_entry *ep;
+
+ full = 0;
+ quick = 0;
+ if (option) {
+ if (!strcasecmp(option, "full"))
+ full = 1;
+ else if (!strcasecmp(option, "quick"))
+ quick = 1;
+ else
+ ap_rprintf(r, "Unknown QSC status option \"%s\"\n",
+ option);
+ }
+
+ qsc_sync_from_scoreboard();
+
+ stats = qsc->stats; /* take a more or less consistent snapshot */
+ nbuckets = 0;
+ nentries = 0;
+ longest_chain = 0;
+ nuribytes = 0;
+ nheaderbytes = 0;
+ nbodybytes = 0;
+ nbodyvas = 0;
+ ndupent = 0;
+ memset(histogram, 0, sizeof histogram);
+ pagesize = getpagesize();
+ if (pagesize <= 0 || (pagesize & (pagesize - 1)) != 0)
+ pagesize = 4096;
+
+ if (!quick) {
+ for (i = 0; i < QSC_HASH_SIZE; i++) {
+ ep = qsc->hash_table[i];
+ if (ep) {
+ int cl;
+
+ nbuckets++;
+
+ cl = 0;
+ do {
+ struct qsc_entry *dp;
+
+ cl++;
+ nentries++;
+ nuribytes += strlen(ep->uri) + 1;
+ nheaderbytes += ep->nkaheaderbytes + ep->nccheaderbytes;
+ nbodybytes += ep->nbodybytes;
+ nbodyvas += QSC_ALIGN(ep->nbodybytes, pagesize);
+
+ for (dp = ep->next; dp; dp = dp->next)
+ if (ep->server == dp->server &&
+ !strcmp(ep->uri, dp->uri))
+ ndupent++;
+
+ ep = ep->next;
+ } while (ep);
+
+ if (cl > longest_chain)
+ longest_chain = cl;
+ histogram[((cl <= QSC_HIST_SIZE) ? cl : QSC_HIST_SIZE) - 1]++;
+ }
+ }
+ }
+
+ /*
+ * ap_vformatter() botches some conversions (like %.2f) so use
+ * sprintf() then ap_rprintf()
+ */
+
+ nlookups = stats.nucreq + stats.nucres + stats.nhits + stats.nmisses;
+ sprintf(buf, "%ld/%ld (%.2f%%)",
+ (long) stats.nhits, (long) nlookups,
+ nlookups ? (double) stats.nhits * 100.0 / (double) nlookups : 0);
+ ap_rprintf(r, fmt, "hit ratio", buf);
+ if (!quick) {
+ ap_atomic uncachable;
+
+ uncachable = stats.nucreq + stats.nucres + stats.nmisses -
+ nentries;
+ sprintf(buf, "%ld/%ld (%.2f%%)",
+ (long) uncachable, (long) nlookups,
+ nlookups ? (double) uncachable * 100.0 / (double) nlookups : 0);
+ ap_rprintf(r, fmt, "uncachable", buf);
+
+ uncachable = stats.nmisses - nentries;
+ sprintf(buf, "%ld/%ld (%.2f%%)",
+ (long) uncachable, (long) stats.nmisses,
+ stats.nmisses ? (double) uncachable * 100.0 / (double) stats.nmisses : 0);
+ ap_rprintf(r, fmt, "uncachable misses", buf);
+ }
+ sprintf(buf, "%ld/%ld (%.2f%%)",
+ (long) stats.nucreq, (long) nlookups,
+ nlookups ? (double) stats.nucreq * 100.0 / (double) nlookups : 0);
+ ap_rprintf(r, fmt, "uncachable requests", buf);
+ sprintf(buf, "%ld/%ld (%.2f%%)",
+ (long) stats.nucres, (long) nlookups,
+ nlookups ? (double) stats.nucres * 100.0 / (double) nlookups : 0);
+ ap_rprintf(r, fmt, "uncachable responses", buf);
+ sprintf(buf, "%ld", (long) stats.nresets);
+ ap_rprintf(r, fmt, "resets", buf);
+
+ ap_rputs("Hash table\n", r);
+ sprintf(buf, "%ld", (long) stats.nfailures);
+ ap_rprintf(r, fmt, "failed insertions", buf);
+ if (!quick) {
+ ap_atomic inuse;
+
+ sprintf(buf, "%d", nentries);
+ ap_rprintf(r, fmt, "entries", buf);
+ sprintf(buf, "%d", ndupent);
+ ap_rprintf(r, fmt, "duplicate entries", buf);
+ sprintf(buf, "%d/%d (%.2f%%)", nbuckets, QSC_HASH_SIZE,
+ (double) nbuckets * 100.0 / (double) QSC_HASH_SIZE);
+ ap_rprintf(r, fmt, "bucket use", buf);
+ sprintf(buf, "%d/%d (%.2f%%)", nbuckets, nentries,
+ nentries ? (double) nbuckets * 100.0 / (double) nentries : 0);
+ ap_rprintf(r, fmt, "hash effectiveness", buf);
+ sprintf(buf, "%d", longest_chain);
+ ap_rprintf(r, fmt, "longest chain", buf);
+ sprintf(buf, "%.1f", (double) nentries / QSC_HASH_SIZE);
+ ap_rprintf(r, fmt, "avg. chain", buf);
+ sprintf(buf, "%.1f", nbuckets ?
+ (double) nentries / (double) nbuckets : 0);
+ ap_rprintf(r, fmt, "avg. nonempty chain", buf);
+
+ ap_rputs(" Chain length histogram:\n ", r);
+ for (i = 1; i < QSC_HIST_SIZE; i++)
+ ap_rprintf(r, "%5d ", i);
+ ap_rprintf(r, "%5d+\n ", i);
+ for (i = 1; i <= QSC_HIST_SIZE; i++)
+ ap_rprintf(r, "%5d ", histogram[i - 1]);
+ ap_rputc('\n', r);
+
+ ap_rputs("Memory use (in bytes)\n", r);
+ sprintf(buf, "%ld", (long) sizeof *qsc);
+ ap_rprintf(r, fmt, "table + misc", buf);
+ sprintf(buf, "%ld", (long) nentries * sizeof (struct qsc_entry));
+ ap_rprintf(r, fmt, "entries", buf);
+ sprintf(buf, "%lu", (unsigned long) nuribytes);
+ ap_rprintf(r, fmt, "URIs", buf);
+ sprintf(buf, "%lu", (unsigned long) nheaderbytes);
+ ap_rprintf(r, fmt, "headers", buf);
+ inuse = qsc_inuse();
+ sprintf(buf, "%ld/%ld (%.2f%%)", (long) inuse, (long) QSC_MAX_SIZE,
+ (double) inuse * 100.0 / (double) QSC_MAX_SIZE);
+ ap_rprintf(r, fmt, "total", buf);
+ sprintf(buf, "%lu", (unsigned long) nbodybytes);
+ ap_rprintf(r, fmt, "mapped file data", buf);
+ sprintf(buf, "%lu (%lu %d-byte pages)", (unsigned long) nbodyvas,
+ (unsigned long) (nbodyvas / pagesize), pagesize);
+ ap_rprintf(r, fmt, "mapped file vaddrs", buf);
+ }
+
+ if (full) {
+ ap_rputs("Full entry info\n", r);
+#ifndef QSC_DEBUG
+ ap_rputs("File names available only -DQSC_DEBUG\n", r);
+#endif
+ ap_rputs(" server * URI @ hash-bucket -> keep-alive-header-bytes;non-keep-alive-header-bytes + body-bytes file-name\n", r);
+
+ for (i = 0; i < QSC_HASH_SIZE; i++) {
+ for (ep = qsc->hash_table[i]; ep; ep = ep->next) {
+ if (ep->server->defn_name)
+ sprintf(buf, "%s:%u", ep->server->defn_name,
+ ep->server->defn_line_number);
+ else
+ strcpy(buf, "main");
+
+ ap_rprintf(r, " %s * %s @ %d -> %lu;%lu + %lu ",
+ buf, ep->uri, i,
+ (unsigned long) ep->nkaheaderbytes,
+ (unsigned long) ep->nccheaderbytes,
+ (unsigned long) ep->nbodybytes);
+#ifdef QSC_DEBUG
+ ap_rputs(ep->filename, r);
+#else
+ ap_rwrite("n/a", 3, r);
+#endif
+ ap_rputc('\n', r);
+ }
+ }
+ }
+ } else
+ ap_rputs("QSC disabled\n", r);
+
+ ap_rputs("\n", r);
+}
+
+#endif
diff -Naur apache_1.3.6+01-07/src/modules/experimental/mod_mmap_static.c apache_1.3.6+01-08/src/modules/experimental/mod_mmap_static.c
--- apache_1.3.6+01-07/src/modules/experimental/mod_mmap_static.c Mon Jul 19 16:43:26 1999
+++ apache_1.3.6+01-08/src/modules/experimental/mod_mmap_static.c Thu Sep 2 10:37:38 1999
@@ -322,6 +322,10 @@
a_file **pmatch;
a_file *match;
int rangestatus, errstatus;
+#ifdef USE_QSC
+ char basic_header[1024];
+ size_t basic_header_len;
+#endif
/* we don't handle anything but GET */
if (r->method_number != M_GET) return DECLINED;
@@ -370,7 +374,13 @@
}
rangestatus = ap_set_byterange(r);
+
+#ifdef USE_QSC
+ basic_header_len = sizeof basic_header;
+ ap_tee_http_header(r, basic_header, &basic_header_len);
+#else
ap_send_http_header(r);
+#endif
if (!r->header_only) {
if (!rangestatus) {
@@ -383,6 +393,17 @@
}
}
}
+
+#ifdef USE_QSC
+ if (basic_header_len > 0) {
+ /* convert from bytes remaining to bytes used */
+ basic_header_len = sizeof basic_header - basic_header_len;
+
+ qsc_insert_request(r, basic_header, basic_header_len,
+ match->mm, match->finfo.st_size, match->filename);
+ }
+#endif
+
return OK;
}
diff -Naur apache_1.3.6+01-07/src/modules/standard/mod_status.c apache_1.3.6+01-08/src/modules/standard/mod_status.c
--- apache_1.3.6+01-07/src/modules/standard/mod_status.c Tue Jul 20 22:44:40 1999
+++ apache_1.3.6+01-08/src/modules/standard/mod_status.c Thu Sep 2 10:38:04 1999
@@ -74,6 +74,9 @@
* /server-status?refresh - Returns page with 1 second refresh
* /server-status?refresh=6 - Returns page with refresh every 6 seconds
* /server-status?auto - Returns page with data for automatic parsing
+#ifdef USE_QSC
+ * /server-status?qsc=... - Returns page with extra QSC status info
+#endif
*
* Mark Cox, mark@ukweb.com, November 1995
*
@@ -209,6 +212,7 @@
#define STAT_OPT_REFRESH 0
#define STAT_OPT_NOTABLE 1
#define STAT_OPT_AUTO 2
+#define STAT_OPT_QSC 3
struct stat_opt {
int id;
@@ -221,6 +225,9 @@
{STAT_OPT_REFRESH, "refresh", "Refresh"},
{STAT_OPT_NOTABLE, "notable", NULL},
{STAT_OPT_AUTO, "auto", NULL},
+#ifdef USE_QSC
+ {STAT_OPT_QSC, "qsc", NULL},
+#endif
{STAT_OPT_END, NULL, NULL}
};
@@ -260,6 +267,9 @@
#endif
clock_t tu, ts, tcu, tcs;
server_rec *vhost;
+#ifdef USE_QSC
+ const char *qscp = NULL;
+#endif
tu = ts = tcu = tcs = 0;
@@ -299,6 +309,12 @@
r->content_type = "text/plain";
short_report = 1;
break;
+#ifdef USE_QSC
+ case STAT_OPT_QSC:
+ if (loc[strlen(status_options[i].form_data_str)] == '=')
+ qscp = &loc[strlen(status_options[i].form_data_str) + 1];
+ break;
+#endif
}
}
i++;
@@ -748,6 +764,11 @@
ap_rputs("you need to use the ExtendedStatus On directive. \n", r);
}
+
+#ifdef USE_QSC
+ ap_rputs("