Changes with Apache 2.0b1
+ *) Make mod_status work with 2.0. This will work for prefork,
+ mpmt_pthread, and dexter. [Ryan Bloom]
+
*) Correct a typo in httpd.conf.
[Kunihiro Tanaka <tanaka@apache.or.jp>] PR#7154
+++ /dev/null
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-/*
- * TODO: Possible additions to this API include getting a list of connection
- * IDs and a list of keys in a particular row.
- */
-
-#ifndef APACHE_MPM_STATUS_H
-#define APACHE_MPM_STATUS_H
-
-#include "apr_lib.h"
-
-/**
- * @package MPM Status API
- */
-
-typedef struct ap_status_table_row_t ap_status_table_row_t;
-/**
- * The MPM status table row structure. MPMs should use this structure in
- * a table to store the status for the requests. This structure stores the
- * status for one connection
- */
-struct ap_status_table_row_t {
- /** The connection id. This is used as a key for the status table */
- long conn_id;
- /** The actual status. This is a table of key-value pairs */
- apr_table_t *data;
-};
-
-/**
- * Get a cell from the status table. Don't mess with the string you get.
- * @param conn_id Connection ID of the current connection
- * @param key The key to determine which status value should be retrieved
- * for the connection.
- * @deffunc const char *ap_get_connection_status(long conn_id, const char *key)
- */
-AP_DECLARE(const char *) ap_get_connection_status(long conn_id, const char *key);
-
-/**
- * Get an array of current connection IDs.
- * @param p The pool to allocate the array out of
- * @return An array of all the current connection IDs
- * @deffunc apr_array_header_t *ap_get_connections(apr_pool_t *p)
- */
-AP_DECLARE(apr_array_header_t *) ap_get_connections(apr_pool_t *p);
-
-/**
- * Get an array of keys from a given connection.
- * @param p Pool to allocate out of
- * @param conn_id Connection ID to get the keys for
- * @return an array of keys from a given connection
- * @deffunc apr_array_header_t *ap_get_connection_keys(apr_pool_t *p, long conn_id)
- */
-AP_DECLARE(apr_array_header_t *) ap_get_connection_keys(apr_pool_t *p,
- long conn_id);
-
-/**
- * Set a cell in the status table. No guarantees are made that long strings
- * won't be truncated.
- * @param conn_id Connection ID to update
- * @param key key to update
- * @param value value to set for the key
- * @deffunc void ap_update_connection_status(long conn_id, const char *key, const char *value)
- */
-AP_DECLARE(void) ap_update_connection_status(long conn_id, const char *key, const char *value);
-
-/**
- * Clear out this connection's status values. Normally called when a
- * connection is closed
- * @param conn_id The connection ID to clear
- * @deffunc void ap_reset_connection_status(long conn_id)
- */
-AP_DECLARE(void) ap_reset_connection_status(long conn_id);
-
-/**
- * Returns the most up-to-date status table available, in the form of an array
- * of ap_status_row_t's.
- * @param p pool to allocate the array out of, generally from the request_rec
- * @return The table of statuses for all connections
- * @deffunc apr_array_header_t *ap_get_status_table(apr_pool_t *p)
- */
-AP_DECLARE(apr_array_header_t *) ap_get_status_table(apr_pool_t *p);
-
-#endif /* APACHE_SERVER_STATS_H */
-
#ifndef APACHE_SCOREBOARD_H
#define APACHE_SCOREBOARD_H
-#include <pthread.h>
#ifdef __cplusplus
extern "C" {
#endif
*/
typedef int ap_generation_t;
-/* stuff which is thread specific */
+/* stuff which is thread/process specific */
typedef struct {
#ifdef OPTIMIZE_TIMEOUTS
vtime_t cur_vtime; /* the child's current vtime */
unsigned short timeout_len; /* length of the timeout */
#endif
- pthread_t tid;
+ int thread_num;
unsigned char status;
unsigned long access_count;
unsigned long bytes_served;
char request[64]; /* We just want an idea... */
server_rec *vhostrec; /* What virtual host is being accessed? */
/* SEE ABOVE FOR SAFE USAGE! */
-} thread_score;
+} short_score;
typedef struct {
ap_generation_t running_generation; /* the generation of children which
} parent_score;
typedef struct {
- thread_score servers[HARD_SERVER_LIMIT][HARD_THREAD_LIMIT];
+ short_score servers[HARD_SERVER_LIMIT][HARD_THREAD_LIMIT];
parent_score parent[HARD_SERVER_LIMIT];
global_score global;
} scoreboard;
void reinit_scoreboard(apr_pool_t *p);
apr_status_t ap_cleanup_shared_mem(void *d);
AP_DECLARE(void) ap_sync_scoreboard_image(void);
-void ap_mpmt_pthread_force_reset_connection_status(long conn_id);
AP_DECLARE(void) reopen_scoreboard(apr_pool_t *p);
AP_DECLARE_DATA extern scoreboard *ap_scoreboard_image;
AP_DECLARE_DATA extern const char *ap_scoreboard_fname;
+AP_DECLARE_DATA extern int ap_extended_status;
+AP_DECLARE_DATA apr_time_t ap_restart_time;
AP_DECLARE_DATA extern ap_generation_t volatile ap_my_generation;
* University of Illinois, Urbana-Champaign.
*/
+/* Status Module. Display lots of internal data about how Apache is
+ * performing and the state of all children processes.
+ *
+ * To enable this, add the following lines into any config file:
+ *
+ * <Location /server-status>
+ * SetHandler server-status
+ * </Location>
+ *
+ * You may want to protect this location by password or domain so no one
+ * else can look at it. Then you can access the statistics with a URL like:
+ *
+ * http://your_server_name/server-status
+ *
+ * /server-status - Returns page using tables
+ * /server-status?notable - Returns page for browsers without table support
+ * /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
+ *
+ * Mark Cox, mark@ukweb.com, November 1995
+ *
+ * 12.11.95 Initial version for www.telescope.org
+ * 13.3.96 Updated to remove rprintf's [Mark]
+ * 18.3.96 Added CPU usage, process information, and tidied [Ben Laurie]
+ * 18.3.96 Make extra Scoreboard variables #definable
+ * 25.3.96 Make short report have full precision [Ben Laurie suggested]
+ * 25.3.96 Show uptime better [Mark/Ben Laurie]
+ * 29.3.96 Better HTML and explanation [Mark/Rob Hartill suggested]
+ * 09.4.96 Added message for non-STATUS compiled version
+ * 18.4.96 Added per child and per slot counters [Jim Jagielski]
+ * 01.5.96 Table format, cleanup, even more spiffy data [Chuck Murcko/Jim J.]
+ * 18.5.96 Adapted to use new rprintf() routine, incidentally fixing a missing
+ * piece in short reports [Ben Laurie]
+ * 21.5.96 Additional Status codes (DNS and LOGGING only enabled if
+ * extended STATUS is enabled) [George Burgyan/Jim J.]
+ * 10.8.98 Allow for extended status info at runtime (no more STATUS)
+ * [Jim J.]
+ */
+
+#define CORE_PRIVATE
#include "httpd.h"
#include "http_config.h"
#include "http_core.h"
#include "http_protocol.h"
-#include "mpm_status.h"
+#include "http_main.h"
+#include "util_script.h"
+#include <time.h>
+#include "scoreboard.h"
+#include "http_log.h"
+
+#ifdef NEXT
+#if (NX_CURRENT_COMPILER_RELEASE == 410)
+#ifdef m68k
+#define HZ 64
+#else
+#define HZ 100
+#endif
+#else
+#include <machine/param.h>
+#endif
+#endif /* NEXT */
+
+#define STATUS_MAXLINE 64
+
+#define KBYTE 1024
+#define MBYTE 1048576L
+#define GBYTE 1073741824L
#ifndef DEFAULT_TIME_FORMAT
#define DEFAULT_TIME_FORMAT "%A, %d-%b-%Y %H:%M:%S %Z"
module AP_MODULE_DECLARE_DATA status_module;
-static int print_status_value(void *data, const char *key, const char *val)
+/*
+ *command-related code. This is here to prevent use of ExtendedStatus
+ * without status_module included.
+ */
+static const char *set_extended_status(cmd_parms *cmd, void *dummy, int arg)
+{
+ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+ if (err != NULL) {
+ return err;
+ }
+ ap_extended_status = arg;
+ return NULL;
+}
+
+static const command_rec status_module_cmds[] =
{
- request_rec *r = (request_rec *) data;
+ AP_INIT_FLAG("ExtendedStatus", set_extended_status, NULL, RSRC_CONF,
+ "\"On\" to enable extended status information, \"Off\" to disable"),
+ {NULL}
+};
+
+/* Format the number of bytes nicely */
+static void format_byte_out(request_rec *r, unsigned long bytes)
+{
+ if (bytes < (5 * KBYTE))
+ ap_rprintf(r, "%d B", (int) bytes);
+ else if (bytes < (MBYTE / 2))
+ ap_rprintf(r, "%.1f kB", (float) bytes / KBYTE);
+ else if (bytes < (GBYTE / 2))
+ ap_rprintf(r, "%.1f MB", (float) bytes / MBYTE);
+ else
+ ap_rprintf(r, "%.1f GB", (float) bytes / GBYTE);
+}
- ap_rprintf(r, "<dt>%s\n<dd>%s\n", key, val);
- return 1;
+static void format_kbyte_out(request_rec *r, unsigned long kbytes)
+{
+ if (kbytes < KBYTE)
+ ap_rprintf(r, "%d kB", (int) kbytes);
+ else if (kbytes < MBYTE)
+ ap_rprintf(r, "%.1f MB", (float) kbytes / KBYTE);
+ else
+ ap_rprintf(r, "%.1f GB", (float) kbytes / MBYTE);
}
+static void show_time(request_rec *r, time_t tsecs)
+{
+ long days, hrs, mins, secs;
+
+ secs = tsecs % 60;
+ tsecs /= 60;
+ mins = tsecs % 60;
+ tsecs /= 60;
+ hrs = tsecs % 24;
+ days = tsecs / 24;
+ if (days)
+ ap_rprintf(r, " %ld day%s", days, days == 1 ? "" : "s");
+ if (hrs)
+ ap_rprintf(r, " %ld hour%s", hrs, hrs == 1 ? "" : "s");
+ if (mins)
+ ap_rprintf(r, " %ld minute%s", mins, mins == 1 ? "" : "s");
+ if (secs)
+ ap_rprintf(r, " %ld second%s", secs, secs == 1 ? "" : "s");
+}
+
+/* Main handler for x-httpd-status requests */
+
+/* ID values for command table */
+
+#define STAT_OPT_END -1
+#define STAT_OPT_REFRESH 0
+#define STAT_OPT_NOTABLE 1
+#define STAT_OPT_AUTO 2
+
+struct stat_opt {
+ int id;
+ const char *form_data_str;
+ const char *hdr_out_str;
+};
+
+static const struct stat_opt status_options[] = /* see #defines above */
+{
+ {STAT_OPT_REFRESH, "refresh", "Refresh"},
+ {STAT_OPT_NOTABLE, "notable", NULL},
+ {STAT_OPT_AUTO, "auto", NULL},
+ {STAT_OPT_END, NULL, NULL}
+};
+
+static char status_flags[SERVER_NUM_STATUS];
+
static int status_handler(request_rec *r)
{
- int i;
- apr_array_header_t *server_status;
- ap_status_table_row_t *status_rows;
+ const char *loc;
+ time_t nowtime = time(NULL);
+ time_t up_time;
+ int j, i, res;
+ int ready = 0;
+ int busy = 0;
+ unsigned long count = 0;
+ unsigned long lres, bytes;
+ unsigned long my_lres, my_bytes, conn_bytes;
+ unsigned short conn_lres;
+ unsigned long bcount = 0;
+ unsigned long kbcount = 0;
+ long req_time;
+#ifndef NO_TIMES
+#ifdef _SC_CLK_TCK
+ float tick = sysconf(_SC_CLK_TCK);
+#else
+ float tick = HZ;
+#endif
+#endif
+ int short_report = 0;
+ int no_table_report = 0;
+ short_score score_record;
+ parent_score ps_record;
+ char stat_buffer[HARD_SERVER_LIMIT * HARD_THREAD_LIMIT];
+ int pid_buffer[HARD_SERVER_LIMIT * HARD_THREAD_LIMIT];
+ clock_t tu, ts, tcu, tcs;
+ server_rec *vhost;
if (strcmp(r->handler, STATUS_MAGIC_TYPE) && strcmp(r->handler, "server-status")) {
return DECLINED;
}
+ tu = ts = tcu = tcs = 0;
+
+ if (!ap_exists_scoreboard_image()) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
+ "Server status unavailable in inetd mode");
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
r->allowed = (1 << M_GET);
if (r->method_number != M_GET)
return DECLINED;
r->content_type = "text/html";
+ /*
+ * Simple table-driven form data set parser that lets you alter the header
+ */
+
+ if (r->args) {
+ i = 0;
+ while (status_options[i].id != STAT_OPT_END) {
+ if ((loc = ap_strstr_c(r->args, status_options[i].form_data_str)) != NULL) {
+ switch (status_options[i].id) {
+ case STAT_OPT_REFRESH:
+ if (*(loc + strlen(status_options[i].form_data_str)) == '='
+ && atol(loc + strlen(status_options[i].form_data_str)
+ + 1) > 0)
+ apr_table_set(r->headers_out,
+ status_options[i].hdr_out_str,
+ loc + strlen(status_options[i].hdr_out_str) + 1);
+ else
+ apr_table_set(r->headers_out,
+ status_options[i].hdr_out_str, "1");
+ break;
+ case STAT_OPT_NOTABLE:
+ no_table_report = 1;
+ break;
+ case STAT_OPT_AUTO:
+ r->content_type = "text/plain";
+ short_report = 1;
+ break;
+ }
+ }
+ i++;
+ }
+ }
+
ap_send_http_header(r);
if (r->header_only)
return 0;
- server_status = ap_get_status_table(r->pool);
-
- ap_rputs(DOCTYPE_HTML_3_2
- "<html><head>\n<title>Apache Status</title>\n</head><body>\n",
- r);
- ap_rputs("<H1>Apache Server Status for ", r);
- ap_rvputs(r, ap_get_server_name(r), "</H1>\n\n", NULL);
- ap_rvputs(r, "Server Version: ",
- ap_get_server_version(), "<br>\n", NULL);
- ap_rvputs(r, "Server Built: ",
- ap_get_server_built(), "<br>\n<hr>\n", NULL);
- ap_rvputs(r, "Current Time: ",
- ap_ht_time(r->pool, apr_now(), DEFAULT_TIME_FORMAT, 0), "<br>\n", NULL);
-
- if (server_status) {
- ap_rprintf(r, "\n%d connections currently being processed\n",
- server_status->nelts);
-
- status_rows = (ap_status_table_row_t *) server_status->elts;
- for (i = 0; i < server_status->nelts; i++) {
- ap_rprintf(r, "<h2>Connection %ld</h2>\n", status_rows[i].conn_id);
- apr_table_do(print_status_value, (void *) r, status_rows[i].data,
- NULL);
+ ap_sync_scoreboard_image();
+ for (i = 0; i < HARD_SERVER_LIMIT; ++i) {
+ for (j = 0; j < HARD_THREAD_LIMIT; ++j) {
+ int indx = (i * HARD_THREAD_LIMIT) + j;
+
+ score_record = ap_scoreboard_image->servers[i][j];
+ ps_record = ap_scoreboard_image->parent[i];
+ res = score_record.status;
+ stat_buffer[indx] = status_flags[res];
+ pid_buffer[indx] = (int) ps_record.pid;
+ if (res == SERVER_READY)
+ ready++;
+ else if (res != SERVER_DEAD)
+ busy++;
+ if (ap_extended_status) {
+ lres = score_record.access_count;
+ bytes = score_record.bytes_served;
+ if (lres != 0 || (res != SERVER_READY && res != SERVER_DEAD)) {
+#ifndef NO_TIMES
+ tu += score_record.times.tms_utime;
+ ts += score_record.times.tms_stime;
+ tcu += score_record.times.tms_cutime;
+ tcs += score_record.times.tms_cstime;
+#endif /* NO_TIMES */
+ count += lres;
+ bcount += bytes;
+ if (bcount >= KBYTE) {
+ kbcount += (bcount >> 10);
+ bcount = bcount & 0x3ff;
+ }
+ }
+ }
+ }
+ }
+
+ up_time = nowtime - ap_restart_time;
+
+ if (!short_report) {
+ ap_rputs(DOCTYPE_HTML_3_2
+ "<HTML><HEAD>\n<TITLE>Apache Status</TITLE>\n</HEAD><BODY>\n",
+ r);
+ ap_rputs("<H1>Apache Server Status for ", r);
+ ap_rvputs(r, ap_get_server_name(r), "</H1>\n\n", NULL);
+ ap_rvputs(r, "Server Version: ",
+ ap_get_server_version(), "<br>\n", NULL);
+ ap_rvputs(r, "Server Built: ",
+ ap_get_server_built(), "<br>\n<hr>\n", NULL);
+ ap_rvputs(r, "Current Time: ",
+ ap_ht_time(r->pool, nowtime, DEFAULT_TIME_FORMAT, 0), "<br>\n", NULL);
+ ap_rvputs(r, "Restart Time: ",
+ ap_ht_time(r->pool, ap_restart_time, DEFAULT_TIME_FORMAT, 0),
+ "<br>\n", NULL);
+ ap_rprintf(r, "Parent Server Generation: %d <br>\n", (int) ap_my_generation);
+ ap_rputs("Server uptime: ", r);
+ show_time(r, up_time);
+ ap_rputs("<br>\n", r);
+ }
+
+ if (ap_extended_status) {
+ if (short_report) {
+ ap_rprintf(r, "Total Accesses: %lu\nTotal kBytes: %lu\n",
+ count, kbcount);
+
+#ifndef NO_TIMES
+ /* Allow for OS/2 not having CPU stats */
+ if (ts || tu || tcu || tcs)
+ ap_rprintf(r, "CPULoad: %g\n",
+ (tu + ts + tcu + tcs) / tick / up_time * 100.);
+#endif
+
+ ap_rprintf(r, "Uptime: %ld\n", (long) (up_time));
+ if (up_time > 0)
+ ap_rprintf(r, "ReqPerSec: %g\n",
+ (float) count / (float) up_time);
+
+ if (up_time > 0)
+ ap_rprintf(r, "BytesPerSec: %g\n",
+ KBYTE * (float) kbcount / (float) up_time);
+
+ if (count > 0)
+ ap_rprintf(r, "BytesPerReq: %g\n",
+ KBYTE * (float) kbcount / (float) count);
+ }
+ else { /* !short_report */
+ ap_rprintf(r, "Total accesses: %lu - Total Traffic: ", count);
+ format_kbyte_out(r, kbcount);
+
+#ifndef NO_TIMES
+ /* Allow for OS/2 not having CPU stats */
+ ap_rputs("<br>\n", r);
+ ap_rprintf(r, "CPU Usage: u%g s%g cu%g cs%g",
+ tu / tick, ts / tick, tcu / tick, tcs / tick);
+
+ if (ts || tu || tcu || tcs)
+ ap_rprintf(r, " - %.3g%% CPU load",
+ (tu + ts + tcu + tcs) / tick / up_time * 100.);
+#endif
+
+ ap_rputs("<br>\n", r);
+
+ if (up_time > 0)
+ ap_rprintf(r, "%.3g requests/sec - ",
+ (float) count / (float) up_time);
+
+ if (up_time > 0) {
+ format_byte_out(r, KBYTE * (float) kbcount / (float) up_time);
+ ap_rputs("/second - ", r);
+ }
+
+ if (count > 0) {
+ format_byte_out(r, KBYTE * (float) kbcount / (float) count);
+ ap_rputs("/request", r);
+ }
+
+ ap_rputs("<br>\n", r);
+ } /* short_report */
+ } /* ap_extended_status */
+
+ if (!short_report)
+ ap_rprintf(r, "\n%d requests currently being processed, %d idle servers\n"
+ ,busy, ready);
+ else
+ ap_rprintf(r, "BusyServers: %d\nIdleServers: %d\n", busy, ready);
+
+ /* send the scoreboard 'table' out */
+
+ if (!short_report)
+ ap_rputs("<PRE>", r);
+ else
+ ap_rputs("Scoreboard: ", r);
+
+ for (i = 0; i < HARD_SERVER_LIMIT; ++i) {
+ for (j = 0; j < HARD_THREAD_LIMIT; ++j) {
+ int indx = (i * HARD_THREAD_LIMIT) + j;
+ ap_rputc(stat_buffer[indx], r);
+ if ((indx % STATUS_MAXLINE == (STATUS_MAXLINE - 1)) && !short_report)
+ ap_rputs("\n", r);
}
}
- ap_rputs("</body></html>\n", r);
+
+ if (short_report)
+ ap_rputs("\n", r);
+ else {
+ ap_rputs("</PRE>\n", r);
+ ap_rputs("Scoreboard Key: <br>\n", r);
+ ap_rputs("\"<B><code>_</code></B>\" Waiting for Connection, \n", r);
+ ap_rputs("\"<B><code>S</code></B>\" Starting up, \n", r);
+ ap_rputs("\"<B><code>R</code></B>\" Reading Request,<BR>\n", r);
+ ap_rputs("\"<B><code>W</code></B>\" Sending Reply, \n", r);
+ ap_rputs("\"<B><code>K</code></B>\" Keepalive (read), \n", r);
+ ap_rputs("\"<B><code>D</code></B>\" DNS Lookup,<BR>\n", r);
+ ap_rputs("\"<B><code>L</code></B>\" Logging, \n", r);
+ ap_rputs("\"<B><code>G</code></B>\" Gracefully finishing, \n", r);
+ ap_rputs("\"<B><code>.</code></B>\" Open slot with no current process<P>\n", r);
+ ap_rputs("<P>\n", r);
+ if (!ap_extended_status) {
+ int j = 0;
+ int k;
+ ap_rputs("PID Key: <br>\n", r);
+ ap_rputs("<PRE>\n", r);
+ for (i = 0; i < HARD_SERVER_LIMIT; ++i) {
+ for (k = 0; k < HARD_THREAD_LIMIT; ++k) {
+ int indx = (i * HARD_THREAD_LIMIT) + j;
+
+ if (stat_buffer[indx] != '.') {
+ ap_rprintf(r, " %d in state: %c ", pid_buffer[i],
+ stat_buffer[indx]);
+ if (++j >= 3) {
+ ap_rputs("\n", r);
+ j = 0;
+ } else
+ ap_rputs(",", r);
+ }
+ }
+ }
+ ap_rputs("\n", r);
+ ap_rputs("</PRE>\n", r);
+ }
+ }
+
+ if (ap_extended_status) {
+ if (!short_report) {
+ if (no_table_report)
+ ap_rputs("<p><hr><h2>Server Details</h2>\n\n", r);
+ else
+#ifdef NO_TIMES
+ /* Allow for OS/2 not having CPU stats */
+ ap_rputs("<p>\n\n<table border=0><tr><th>Srv<th>PID<th>Acc<th>M\n<th>SS<th>Req<th>Conn<th>Child<th>Slot<th>Client<th>VHost<th>Request</tr>\n\n", r);
+#else
+ ap_rputs("<p>\n\n<table border=0><tr><th>Srv<th>PID<th>Acc<th>M<th>CPU\n<th>SS<th>Req<th>Conn<th>Child<th>Slot<th>Client<th>VHost<th>Request</tr>\n\n", r);
+#endif
+ }
+
+ for (i = 0; i < HARD_SERVER_LIMIT; ++i) {
+ for (j = 0; j < HARD_THREAD_LIMIT; ++j) {
+ score_record = ap_scoreboard_image->servers[i][j];
+ ps_record = ap_scoreboard_image->parent[i];
+ vhost = score_record.vhostrec;
+ if (ps_record.generation != ap_my_generation) {
+ vhost = NULL;
+ }
+
+#if defined(NO_GETTIMEOFDAY)
+#ifndef NO_TIMES
+ if (score_record.start_time == (clock_t) 0)
+#endif /* NO_TIMES */
+ req_time = 0L;
+#ifndef NO_TIMES
+ else {
+ req_time = score_record.stop_time - score_record.start_time;
+ req_time = (req_time * 1000) / (int) tick;
+ }
+#endif /* NO_TIMES */
+#else
+ if (score_record.start_time == 0L &&
+ score_record.start_time == 0L)
+ req_time = 0L;
+ else
+ req_time =
+ ((score_record.stop_time - score_record.start_time) * 1000) +
+ ((score_record.stop_time - score_record.start_time) / 1000);
+#endif
+ if (req_time < 0L)
+ req_time = 0L;
+
+ lres = score_record.access_count;
+ my_lres = score_record.my_access_count;
+ conn_lres = score_record.conn_count;
+ bytes = score_record.bytes_served;
+ my_bytes = score_record.my_bytes_served;
+ conn_bytes = score_record.conn_bytes;
+ if (lres != 0 || (score_record.status != SERVER_READY
+ && score_record.status != SERVER_DEAD)) {
+ if (!short_report) {
+ if (no_table_report) {
+ if (score_record.status == SERVER_DEAD)
+ ap_rprintf(r,
+ "<b>Server %d-%d</b> (-): %d|%lu|%lu [",
+ i, (int) ps_record.generation, (int) conn_lres,
+ my_lres, lres);
+ else
+ ap_rprintf(r,
+ "<b>Server %d-%d</b> (%d): %d|%lu|%lu [",
+ i, (int) ps_record.generation,
+ (int) ps_record.pid,
+ (int) conn_lres, my_lres, lres);
+
+ switch (score_record.status) {
+ case SERVER_READY:
+ ap_rputs("Ready", r);
+ break;
+ case SERVER_STARTING:
+ ap_rputs("Starting", r);
+ break;
+ case SERVER_BUSY_READ:
+ ap_rputs("<b>Read</b>", r);
+ break;
+ case SERVER_BUSY_WRITE:
+ ap_rputs("<b>Write</b>", r);
+ break;
+ case SERVER_BUSY_KEEPALIVE:
+ ap_rputs("<b>Keepalive</b>", r);
+ break;
+ case SERVER_BUSY_LOG:
+ ap_rputs("<b>Logging</b>", r);
+ break;
+ case SERVER_BUSY_DNS:
+ ap_rputs("<b>DNS lookup</b>", r);
+ break;
+ case SERVER_DEAD:
+ ap_rputs("Dead", r);
+ break;
+ case SERVER_GRACEFUL:
+ ap_rputs("Graceful", r);
+ break;
+ default:
+ ap_rputs("?STATE?", r);
+ break;
+ }
+#ifdef NO_TIMES
+ /* Allow for OS/2 not having CPU stats */
+ ap_rprintf(r, "]\n %.0f %ld (",
+#else
+
+ ap_rprintf(r, "] u%g s%g cu%g cs%g\n %.0f %ld (",
+ score_record.times.tms_utime / tick,
+ score_record.times.tms_stime / tick,
+ score_record.times.tms_cutime / tick,
+ score_record.times.tms_cstime / tick,
+#endif
+#ifdef OPTIMIZE_TIMEOUTS
+ difftime(nowtime, ps_record.last_rtime),
+#else
+ difftime(nowtime, score_record.last_used),
+#endif
+ (long) req_time);
+ format_byte_out(r, conn_bytes);
+ ap_rputs("|", r);
+ format_byte_out(r, my_bytes);
+ ap_rputs("|", r);
+ format_byte_out(r, bytes);
+ ap_rputs(")\n", r);
+ ap_rprintf(r, " <i>%s {%s}</i> <b>[%s]</b><br>\n\n",
+ ap_escape_html(r->pool, score_record.client),
+ ap_escape_html(r->pool, score_record.request),
+ vhost ? ap_escape_html(r->pool,
+ vhost->server_hostname) : "(unavailable)");
+ }
+ else { /* !no_table_report */
+ if (score_record.status == SERVER_DEAD)
+ ap_rprintf(r,
+ "<tr><td><b>%d-%d</b><td>-<td>%d/%lu/%lu",
+ i, (int) ps_record.generation,
+ (int) conn_lres, my_lres, lres);
+ else
+ ap_rprintf(r,
+ "<tr><td><b>%d-%d</b><td>%d<td>%d/%lu/%lu",
+ i, (int) ps_record.generation,
+ (int) ps_record.pid, (int) conn_lres,
+ my_lres, lres);
+
+ switch (score_record.status) {
+ case SERVER_READY:
+ ap_rputs("<td>_", r);
+ break;
+ case SERVER_STARTING:
+ ap_rputs("<td><b>S</b>", r);
+ break;
+ case SERVER_BUSY_READ:
+ ap_rputs("<td><b>R</b>", r);
+ break;
+ case SERVER_BUSY_WRITE:
+ ap_rputs("<td><b>W</b>", r);
+ break;
+ case SERVER_BUSY_KEEPALIVE:
+ ap_rputs("<td><b>K</b>", r);
+ break;
+ case SERVER_BUSY_LOG:
+ ap_rputs("<td><b>L</b>", r);
+ break;
+ case SERVER_BUSY_DNS:
+ ap_rputs("<td><b>D</b>", r);
+ break;
+ case SERVER_DEAD:
+ ap_rputs("<td>.", r);
+ break;
+ case SERVER_GRACEFUL:
+ ap_rputs("<td>G", r);
+ break;
+ default:
+ ap_rputs("<td>?", r);
+ break;
+ }
+#ifdef NO_TIMES
+ /* Allow for OS/2 not having CPU stats */
+ ap_rprintf(r, "\n<td>%.0f<td>%ld",
+#else
+ ap_rprintf(r, "\n<td>%.2f<td>%.0f<td>%ld",
+ (score_record.times.tms_utime +
+ score_record.times.tms_stime +
+ score_record.times.tms_cutime +
+ score_record.times.tms_cstime) / tick,
+#endif
+#ifdef OPTIMIZE_TIMEOUTS
+ difftime(nowtime, ps_record.last_rtime),
+#else
+ difftime(nowtime, score_record.last_used),
+#endif
+ (long) req_time);
+ ap_rprintf(r, "<td>%-1.1f<td>%-2.2f<td>%-2.2f\n",
+ (float) conn_bytes / KBYTE, (float) my_bytes / MBYTE,
+ (float) bytes / MBYTE);
+ if (score_record.status == SERVER_BUSY_READ)
+ ap_rprintf(r,
+ "<td>?<td nowrap>?<td nowrap>..reading.. </tr>\n\n");
+ else
+ ap_rprintf(r,
+ "<td>%s<td nowrap>%s<td nowrap>%s</tr>\n\n",
+ ap_escape_html(r->pool, score_record.client),
+ vhost ? ap_escape_html(r->pool,
+ vhost->server_hostname) : "(unavailable)",
+ ap_escape_html(r->pool, score_record.request));
+ } /* no_table_report */
+ } /* !short_report */
+ } /* if (<active child>) */
+ } /* for () */
+ }
+
+ if (!(short_report || no_table_report)) {
+#ifdef NO_TIMES
+ ap_rputs("</table>\n \
+<hr> \
+<table>\n \
+<tr><th>Srv<td>Child Server number - generation\n \
+<tr><th>PID<td>OS process ID\n \
+<tr><th>Acc<td>Number of accesses this connection / this child / this slot\n \
+<tr><th>M<td>Mode of operation\n \
+<tr><th>SS<td>Seconds since beginning of most recent request\n \
+<tr><th>Req<td>Milliseconds required to process most recent request\n \
+<tr><th>Conn<td>Kilobytes transferred this connection\n \
+<tr><th>Child<td>Megabytes transferred this child\n \
+<tr><th>Slot<td>Total megabytes transferred this slot\n \
+</table>\n", r);
+#else
+ ap_rputs("</table>\n \
+<hr> \
+<table>\n \
+<tr><th>Srv<td>Child Server number - generation\n \
+<tr><th>PID<td>OS process ID\n \
+<tr><th>Acc<td>Number of accesses this connection / this child / this slot\n \
+<tr><th>M<td>Mode of operation\n \
+<tr><th>CPU<td>CPU usage, number of seconds\n \
+<tr><th>SS<td>Seconds since beginning of most recent request\n \
+<tr><th>Req<td>Milliseconds required to process most recent request\n \
+<tr><th>Conn<td>Kilobytes transferred this connection\n \
+<tr><th>Child<td>Megabytes transferred this child\n \
+<tr><th>Slot<td>Total megabytes transferred this slot\n \
+</table>\n", r);
+#endif
+ }
+
+ } else {
+
+ if (!short_report) {
+ ap_rputs("<hr>To obtain a full report with current status information ", r);
+ ap_rputs("you need to use the <code>ExtendedStatus On</code> directive. \n", r);
+ }
+
+ }
+
+ if (!short_report) {
+ ap_rputs(ap_psignature("<HR>\n",r), r);
+ ap_rputs("</BODY></HTML>\n", r);
+ }
+
return 0;
}
+
+static void status_init(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
+{
+ status_flags[SERVER_DEAD] = '.'; /* We don't want to assume these are in */
+ status_flags[SERVER_READY] = '_'; /* any particular order in scoreboard.h */
+ status_flags[SERVER_STARTING] = 'S';
+ status_flags[SERVER_BUSY_READ] = 'R';
+ status_flags[SERVER_BUSY_WRITE] = 'W';
+ status_flags[SERVER_BUSY_KEEPALIVE] = 'K';
+ status_flags[SERVER_BUSY_LOG] = 'L';
+ status_flags[SERVER_BUSY_DNS] = 'D';
+ status_flags[SERVER_GRACEFUL] = 'G';
+}
+
static void register_hooks(apr_pool_t *p)
{
ap_hook_handler(status_handler, NULL, NULL, APR_HOOK_MIDDLE);
+ ap_hook_post_config(status_init, NULL, NULL, APR_HOOK_MIDDLE);
}
module AP_MODULE_DECLARE_DATA status_module =
{
STANDARD20_MODULE_STUFF,
- NULL, /* create per-dir config */
- NULL, /* merge per-dir config */
+ NULL, /* dir config creater */
+ NULL, /* dir merger --- default is to override */
NULL, /* server config */
NULL, /* merge server config */
- NULL, /* command table */
- register_hooks /* register hooks */
+ status_module_cmds, /* command table */
+ register_hooks /* register_hooks */
};
+
#include "util_date.h" /* For parseHTTPdate and BAD_DATE */
#include "util_charset.h"
#include "util_ebcdic.h"
-#include "mpm_status.h"
#include "mod_core.h"
char l[DEFAULT_LIMIT_REQUEST_LINE + 2]; /* getline's two extra for \n\0 */
const char *ll = l;
const char *uri;
+#if 0
conn_rec *conn = r->connection;
+#endif
int major = 1, minor = 0; /* Assume HTTP/1.0 if non-"HTTP" protocol */
int len;
r->request_time = apr_now();
r->the_request = apr_pstrdup(r->pool, l);
r->method = ap_getword_white(r->pool, &ll);
- ap_update_connection_status(conn->id, "Method", r->method);
+#if 0
+/* XXX If we want to keep track of the Method, the protocol module should do
+ * it. That support isn't in the scoreboard yet. Hopefully next week
+ * sometime. rbb */
+ ap_update_connection_status(AP_CHILD_THREAD_FROM_ID(conn->id), "Method", r->method);
+#endif
uri = ap_getword_white(r->pool, &ll);
/* Provide quick information about the request method as soon as known */
r->assbackwards = (ll[0] == '\0');
r->protocol = apr_pstrdup(r->pool, ll[0] ? ll : "HTTP/0.9");
- ap_update_connection_status(conn->id, "Protocol", r->protocol);
+/* XXX If we want to keep track of the Method, the protocol module should do
+ * it. That support isn't in the scoreboard yet. Hopefully next week
+ * sometime. rbb
+ ap_update_connection_status(conn->id, "Protocol", r->protocol);
+ */
if (2 == sscanf(r->protocol, "HTTP/%u.%u", &major, &minor)
&& minor < HTTP_VERSION(1,0)) /* don't allow HTTP/0.1000 */
util_script.c util_uri.c util_md5.c util_cfgtree.c util_ebcdic.c \
rfc1413.c connection.c listen.c \
mpm_common.c util_charset.c util_debug.c util_xml.c \
- util_filter.c exports.c buildmark.c
+ util_filter.c exports.c buildmark.c scoreboard.c
targets = delete-exports $(LTLIBRARY_NAME)
AC_CHECK_FUNCS(
syslog \
)
+
+dnl Obsolete scoreboard code uses this.
+ AC_CHECK_HEADERS(sys/times.h)
+ AC_CHECK_FUNCS(times)
#include "http_request.h"
#include "http_protocol.h"
#include "ap_mpm.h"
-#include "mpm_status.h"
+#include "mpm_default.h"
#include "http_config.h"
#include "http_vhost.h"
+#include "scoreboard.h"
#include "http_log.h"
#include "util_filter.h"
* until no requests are left or we decide to close.
*/
- ap_update_connection_status(c->id, "Status", "Reading");
+ ap_update_child_status(AP_CHILD_THREAD_FROM_ID(c->id), SERVER_BUSY_READ, NULL);
while ((r = ap_read_request(c)) != NULL) {
/* process the request if it was read without error */
- ap_update_connection_status(c->id, "Status", "Writing");
+ ap_update_child_status(AP_CHILD_THREAD_FROM_ID(c->id), SERVER_BUSY_WRITE, NULL);
if (r->status == HTTP_OK)
ap_process_request(r);
if (!c->keepalive || c->aborted)
break;
- ap_update_connection_status(c->id, "Status", "Keepalive");
+ ap_update_child_status(AP_CHILD_THREAD_FROM_ID(c->id), SERVER_BUSY_KEEPALIVE, NULL);
apr_destroy_pool(r->pool);
if (ap_graceful_stop_signalled())
break;
}
- ap_reset_connection_status(c->id);
+ ap_update_child_status(AP_CHILD_THREAD_FROM_ID(c->id), SERVER_READY, NULL);
return OK;
}
LTLIBRARY_NAME = libbeos.la
-LTLIBRARY_SOURCES = beos.c scoreboard.c
+LTLIBRARY_SOURCES = beos.c
include $(top_srcdir)/build/ltlib.mk
+++ /dev/null
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#include "httpd.h"
-#include "http_log.h"
-#include "http_main.h"
-#include "http_core.h"
-#include "http_config.h"
-#include "mpm_status.h"
-#include "mpm.h" /* includes scoreboard.h */
-#include "beosd.h"
-#include "http_conf_globals.h"
-#include "beos.h"
-
-scoreboard *ap_scoreboard_image = NULL;
-extern apr_pool_t * pconf;
-static int maintain_connection_status = 1;
-
-void reinit_scoreboard(apr_pool_t *p)
-{
- if (!ap_scoreboard_image)
- ap_scoreboard_image = (scoreboard *) malloc(SCOREBOARD_SIZE);
- if (ap_scoreboard_image == NULL) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "Ouch! Out of memory reiniting scoreboard!");
- }
- memset(ap_scoreboard_image, 0, SCOREBOARD_SIZE);
-}
-
-void cleanup_scoreboard(void)
-{
- ap_assert(ap_scoreboard_image);
- free(ap_scoreboard_image);
- ap_scoreboard_image = NULL;
-}
-
-AP_DECLARE(int) ap_exists_scoreboard_image(void)
-{
- return (ap_scoreboard_image ? 1 : 0);
-}
-
-
-void ap_update_connection_status(long conn_id, const char *key,
- const char *value)
-{
- int i = 0;
- status_table_entry *ss;
-
- if (!maintain_connection_status) return;
- while (i < STATUSES_PER_CONNECTION) {
- ss = &(ap_scoreboard_image->table[conn_id][i]);
- if (ss->key[0] == '\0') {
- break;
- }
- if (0 == strcmp(ss->key, key)) {
- apr_cpystrn(ss->value, value, VALUE_LENGTH);
- return;
- }
- i++;
- }
- if (i >= STATUSES_PER_CONNECTION) {
- return;
- }
- apr_cpystrn(ss->key, key, KEY_LENGTH);
- apr_cpystrn(ss->value, value, VALUE_LENGTH);
- return;
-}
-
-void ap_reset_connection_status(long conn_id)
-{
- if (maintain_connection_status) {
- ap_beos_force_reset_connection_status(conn_id);
- }
-}
-
-void ap_beos_set_maintain_connection_status(int flag) {
- maintain_connection_status = flag;
- return;
-}
-
-void ap_beos_force_reset_connection_status(long conn_id)
-{
- int i;
-
- for (i = 0; i < STATUSES_PER_CONNECTION; i++) {
- ap_scoreboard_image->table[conn_id][i].key[0] = '\0';
- }
-}
-
-const char *ap_get_connection_status(long conn_id, const char *key)
-{
- int i = 0;
- status_table_entry *ss;
-
- if (!maintain_connection_status) return "";
- while (i < STATUSES_PER_CONNECTION) {
- ss = &(ap_scoreboard_image->table[conn_id][i]);
- if (ss->key[0] == '\0') {
- break;
- }
- if (0 == strcmp(ss->key, key)) {
- return ss->value;
- }
- }
-
- return NULL;
-}
-
-apr_array_header_t *ap_get_connections(apr_pool_t *p)
-{
- int i;
- apr_array_header_t *connection_list;
- long *array_slot;
-
- connection_list = apr_make_array(p, 0, sizeof(long));
- for (i = 0; i < ap_max_child_assigned; i++) {
- if (ap_scoreboard_image->table[i][0].key[0] != '\0') {
- array_slot = apr_push_array(connection_list);
- *array_slot = i;
- }
- }
- return connection_list;
-}
-
-apr_array_header_t *ap_get_connection_keys(apr_pool_t *p, long conn_id)
-{
- int i = 0;
- status_table_entry *ss;
- apr_array_header_t *key_list;
- char **array_slot;
-
- key_list = apr_make_array(p, 0, KEY_LENGTH * sizeof(char));
- while (i < STATUSES_PER_CONNECTION) {
- ss = &(ap_scoreboard_image->table[conn_id][i]);
- if (ss->key[0] == '\0') {
- break;
- }
- array_slot = apr_push_array(key_list);
- *array_slot = (char*)apr_pstrdup(p, ss->key);
- i++;
- }
- return key_list;
-}
-
-apr_array_header_t *ap_get_status_table(apr_pool_t *p)
-{
- int i, j;
- apr_array_header_t *server_status;
- ap_status_table_row_t *array_slot;
- status_table_entry *ss;
-
- server_status = apr_make_array(p, 0, sizeof(ap_status_table_row_t));
-
- for (i = 0; i < ap_max_child_assigned; i++) {
- if (ap_scoreboard_image->table[i][0].key[0] == '\0')
- continue;
- array_slot = apr_push_array(server_status);
- array_slot->data = apr_make_table(p, 0);
- array_slot->conn_id = i;
-
- for (j = 0; j < STATUSES_PER_CONNECTION; j++) {
- ss = &(ap_scoreboard_image->table[i][j]);
- if (ss->key[0] != '\0') {
- apr_table_add(array_slot->data, ss->key, ss->value);
- }
- else {
- break;
- }
- }
- }
- return server_status;
-}
+++ /dev/null
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#ifndef BEOS_SCOREBOARD_H
-#define BEOS_SCOREBOARD_H
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-#include <sys/times.h>
-#include "mpm_default.h" /* For HARD_.*_LIMIT */
-
-AP_DECLARE(int) ap_exists_scoreboard_image(void);
-void reinit_scoareboard(apr_pool_t *p);
-void cleanup_scoreboard(void);
-void ap_beos_set_maintain_connection_status(int flag);
-void ap_beos_force_reset_connection_status(long conn_id);
-void reinit_scoreboard(apr_pool_t *p);
-void update_scoreboard_global(void);
-AP_DECLARE(int) find_child_by_pid(int pid);
-int ap_update_child_status(int child_num, int thread_num, int status, request_rec *r);
-void ap_time_process_request(int child_num, int thread_num, int status);
-
-/* Add support for connection table functions */
-
-#define KEY_LENGTH 16
-#define VALUE_LENGTH 64
-
-typedef struct {
- char key[KEY_LENGTH];
- char value[VALUE_LENGTH];
-} status_table_entry;
-
-#define STATUSES_PER_CONNECTION 10
-
-typedef struct {
- status_table_entry
- table[HARD_THREAD_LIMIT][STATUSES_PER_CONNECTION];
-} scoreboard;
-
-#define SCOREBOARD_SIZE sizeof(scoreboard)
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* !BEOS_SCOREBOARD_H */
LTLIBRARY_NAME = libdexter.la
-LTLIBRARY_SOURCES = dexter.c scoreboard.c
+LTLIBRARY_SOURCES = dexter.c
include $(top_srcdir)/build/ltlib.mk
static int max_threads = 0;
static int max_requests_per_child = 0;
static const char *ap_pid_fname=NULL;
-AP_DECLARE_DATA const char *ap_scoreboard_fname=NULL;
static int num_daemons=0;
static int workers_may_exit = 0;
static int requests_this_child;
* many child processes in this MPM.
*/
int ap_max_daemons_limit = -1;
+int ap_threads_per_child = HARD_THREAD_LIMIT;
char ap_coredump_dir[MAX_STRING_LEN];
static int volatile shutdown_pending;
static int volatile restart_pending;
static int volatile is_graceful;
+ap_generation_t volatile ap_my_generation=0;
/*
* ap_start_shutdown() and ap_start_restart(), below, are a first stab at
ap_sock_disable_nagle(sock);
+ (void) ap_update_child_status(AP_CHILD_THREAD_FROM_ID(conn_id),
+ SERVER_BUSY_READ, (request_rec *) NULL);
+
current_conn = ap_new_connection(p, ap_server_conf, sock, conn_id);
ap_process_connection(current_conn);
pthread_mutex_unlock(&thread_pool_parent_mutex);
apr_create_pool(&ptrans, tpool);
+ (void) ap_update_child_status(child_num, thread_num, SERVER_STARTING,
+ (request_rec *) NULL);
+
+
apr_setup_poll(&pollset, num_listenfds+1, tpool);
for(n=0 ; n <= num_listenfds ; ++n)
apr_add_poll_socket(pollset, listenfds[n], APR_POLLIN);
else {
thread_just_started = 0;
}
+
+ (void) ap_update_child_status(child_num, thread_num, SERVER_READY,
+ (request_rec *) NULL);
+
if ((rv = SAFE_ACCEPT(apr_lock(accept_mutex)))
!= APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
}
pthread_mutex_lock(&thread_pool_parent_mutex);
- apr_destroy_pool(tpool);
+ ap_update_child_status(child_num, thread_num, SERVER_DEAD,
+ (request_rec *) NULL);
pthread_mutex_unlock(&thread_pool_parent_mutex);
pthread_mutex_lock(&worker_thread_count_mutex);
worker_thread_count--;
child_main(slot);
}
+ (void) ap_update_child_status(slot, 0, SERVER_STARTING, (request_rec *) NULL);
+
if ((pid = fork()) == -1) {
ap_log_error(APLOG_MARK, APLOG_ERR, errno, s,
"fork: Unable to fork new process");
+ (void) ap_update_child_status(slot, 0, SERVER_DEAD, (request_rec *) NULL);
/* In case system resources are maxxed out, we don't want
Apache running away with the CPU trying to fork over and
over and over again. */
child_slot = -1;
for (i = 0; i < ap_max_daemons_limit; ++i) {
if (ap_child_table[i].pid == pid.pid) {
- int j;
-
child_slot = i;
- for (j = 0; j < HARD_THREAD_LIMIT; j++) {
- ap_dexter_force_reset_connection_status(i * HARD_THREAD_LIMIT + j);
- }
break;
}
}
if (child_slot >= 0) {
ap_child_table[child_slot].pid = 0;
+ ap_update_child_status(child_slot, i, SERVER_DEAD, (request_rec *) NULL);
if (remaining_children_to_start
&& child_slot < num_daemons) {
ap_scoreboard_fname = DEFAULT_SCOREBOARD;
lock_fname = DEFAULT_LOCKFILE;
max_requests_per_child = DEFAULT_MAX_REQUESTS_PER_CHILD;
- ap_dexter_set_maintain_connection_status(1);
apr_cpystrn(ap_coredump_dir, ap_server_root, sizeof(ap_coredump_dir));
}
return NULL;
}
-static const char *set_maintain_connection_status(cmd_parms *cmd,
- void *dummy, int arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- ap_dexter_set_maintain_connection_status(arg != 0);
- return NULL;
-}
-
static const char *set_coredumpdir (cmd_parms *cmd, void *dummy, const char *arg)
{
apr_finfo_t finfo;
"Maximum number of threads per child"),
AP_INIT_TAKE1("MaxRequestsPerChild", set_max_requests, NULL, RSRC_CONF,
"Maximum number of requests a particular child serves before dying."),
-AP_INIT_FLAG("ConnectionStatus", set_maintain_connection_status, NULL, RSRC_CONF,
- "Whether or not to maintain status information on current connections"),
AP_INIT_TAKE1("CoreDumpDirectory", set_coredumpdir, NULL, RSRC_CONF,
"The location of the directory Apache changes to before dumping core"),
{ NULL }
unsigned char status;
} ap_ctable;
+extern int ap_threads_per_child;
extern int ap_max_daemons_limit;
extern ap_ctable ap_child_table[HARD_SERVER_LIMIT];
extern server_rec *ap_server_conf;
#ifndef APACHE_MPM_DEFAULT_H
#define APACHE_MPM_DEFAULT_H
+#define AP_ID_FROM_CHILD_THREAD(c, t) ((c * HARD_SERVER_LIMIT) + HARD_THREAD_LIMIT)
+#define AP_CHILD_THREAD_FROM_ID(i) (i / HARD_SERVER_LIMIT), (i % HARD_THREAD_LIMIT)
+
/* Number of threads to spawn off by default --- also, if fewer than
* this free when the caretaker checks, it will spawn more.
*/
+++ /dev/null
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#include "apr_strings.h"
-#include "ap_config.h"
-#include "httpd.h"
-#include "http_log.h"
-#include "http_main.h"
-#include "http_core.h"
-#include "http_config.h"
-#include "unixd.h"
-#include "http_conf_globals.h"
-#include "mpm_status.h"
-#include "scoreboard.h"
-#include "mpm.h" /* for ap_max_daemons_limit */
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-static scoreboard *ap_scoreboard_image = NULL;
-
-/*****************************************************************
- *
- * Dealing with the scoreboard... a lot of these variables are global
- * only to avoid getting clobbered by the longjmp() that happens when
- * a hard timeout expires...
- *
- * We begin with routines which deal with the file itself...
- */
-
-#if APR_HAS_SHARED_MEMORY
-#include "apr_shmem.h"
-
-static apr_shmem_t *scoreboard_shm = NULL;
-
-apr_status_t ap_cleanup_shared_mem(void *d)
-{
- apr_shm_free(scoreboard_shm, ap_scoreboard_image);
- ap_scoreboard_image = NULL;
- apr_shm_destroy(scoreboard_shm);
- return APR_SUCCESS;
-}
-
-static void setup_shared_mem(apr_pool_t *p)
-{
- char buf[512];
- char errmsg[120];
- const char *fname;
- apr_status_t rv;
-
- fname = ap_server_root_relative(p, ap_scoreboard_fname);
- rv = apr_shm_init(&scoreboard_shm, SCOREBOARD_SIZE, fname, p);
- if (rv != APR_SUCCESS) {
- apr_snprintf(buf, sizeof(buf), "%s: could not open(create) scoreboard: %s",
- ap_server_argv0, apr_strerror(rv, errmsg, sizeof errmsg));
- fprintf(stderr, "%s\n", buf);
- exit(APEXIT_INIT);
- }
- ap_scoreboard_image = apr_shm_malloc(scoreboard_shm, SCOREBOARD_SIZE);
- if (ap_scoreboard_image == NULL) {
- apr_snprintf(buf, sizeof(buf), "%s: cannot allocate scoreboard",
- ap_server_argv0);
- perror(buf); /* o.k. since MM sets errno */
- apr_shm_destroy(scoreboard_shm);
- exit(APEXIT_INIT);
- }
- apr_register_cleanup(p, NULL, ap_cleanup_shared_mem, apr_null_cleanup);
-}
-
-void reinit_scoreboard(apr_pool_t *p)
-{
- if (ap_scoreboard_image == NULL) {
- setup_shared_mem(p);
- }
- memset(ap_scoreboard_image, 0, SCOREBOARD_SIZE);
-}
-#endif /* APR_SHARED_MEM */
-
-/****
- * Above code is shmem code. Below code is interacting with the shmem
- ****/
-
-static int maintain_connection_status = 1;
-
-void ap_dexter_set_maintain_connection_status(int flag) {
- maintain_connection_status = flag;
- return;
-}
-
-/* Useful to erase the status of children that might be from previous
- * generations */
-void ap_dexter_force_reset_connection_status(long conn_id)
-{
- int i;
-
- for (i = 0; i < STATUSES_PER_CONNECTION; i++) {
- ap_scoreboard_image->table[conn_id][i].key[0] = '\0';
- }
-}
-
-void ap_reset_connection_status(long conn_id)
-{
- if (maintain_connection_status) {
- ap_dexter_force_reset_connection_status(conn_id);
- }
-}
-
-/* Don't mess with the string you get back from this function */
-const char *ap_get_connection_status(long conn_id, const char *key)
-{
- int i = 0;
- status_table_entry *ss;
-
- if (!maintain_connection_status) return "";
- while (i < STATUSES_PER_CONNECTION) {
- ss = &(ap_scoreboard_image->table[conn_id][i]);
- if (ss->key[0] == '\0') {
- break;
- }
- if (0 == strcmp(ss->key, key)) {
- return ss->value;
- }
- }
-
- return NULL;
-}
-
-apr_array_header_t *ap_get_connections(apr_pool_t *p)
-{
- int i;
- apr_array_header_t *connection_list;
- long *array_slot;
-
- connection_list = apr_make_array(p, 0, sizeof(long));
- /* We assume that there is a connection iff it has an entry in the status
- * table. Connections without any status sound problematic to me, so this
- * is probably for the best. - manoj */
- for (i = 0; i < ap_max_daemons_limit*HARD_THREAD_LIMIT; i++) {
- if (ap_scoreboard_image->table[i][0].key[0] != '\0') {
- array_slot = apr_push_array(connection_list);
- *array_slot = i;
- }
- }
- return connection_list;
-}
-
-apr_array_header_t *ap_get_connection_keys(apr_pool_t *p, long conn_id)
-{
- int i = 0;
- status_table_entry *ss;
- apr_array_header_t *key_list;
- char **array_slot;
-
- key_list = apr_make_array(p, 0, KEY_LENGTH * sizeof(char));
- while (i < STATUSES_PER_CONNECTION) {
- ss = &(ap_scoreboard_image->table[conn_id][i]);
- if (ss->key[0] == '\0') {
- break;
- }
- array_slot = apr_push_array(key_list);
- *array_slot = apr_pstrdup(p, ss->key);
- i++;
- }
- return key_list;
-}
-
-/* Note: no effort is made here to prevent multiple threads from messing with
- * a single connection at the same time. ap_update_connection_status should
- * only be called by the thread that owns the connection */
-
-void ap_update_connection_status(long conn_id, const char *key,
- const char *value)
-{
- int i = 0;
- status_table_entry *ss;
-
- if (!maintain_connection_status) return;
- while (i < STATUSES_PER_CONNECTION) {
- ss = &(ap_scoreboard_image->table[conn_id][i]);
- if (ss->key[0] == '\0') {
- break;
- }
- if (0 == strcmp(ss->key, key)) {
- apr_cpystrn(ss->value, value, VALUE_LENGTH);
- return;
- }
- i++;
- }
- /* Not found. Add an entry for this value */
- if (i >= STATUSES_PER_CONNECTION) {
- /* No room. Oh well, not much anyone can do about it. */
- return;
- }
- apr_cpystrn(ss->key, key, KEY_LENGTH);
- apr_cpystrn(ss->value, value, VALUE_LENGTH);
- return;
-}
-
-apr_array_header_t *ap_get_status_table(apr_pool_t *p)
-{
- int i, j;
- apr_array_header_t *server_status;
- ap_status_table_row_t *array_slot;
- status_table_entry *ss;
-
- server_status = apr_make_array(p, 0, sizeof(ap_status_table_row_t));
-
- /* Go ahead and return what's in the connection status table even if we
- * aren't maintaining it. We can at least look at what children from
- * previous generations are up to. */
-
- for (i = 0; i < ap_max_daemons_limit*HARD_THREAD_LIMIT; i++) {
- if (ap_scoreboard_image->table[i][0].key[0] == '\0')
- continue;
- array_slot = apr_push_array(server_status);
- array_slot->data = apr_make_table(p, 0);
- array_slot->conn_id = i;
-
- for (j = 0; j < STATUSES_PER_CONNECTION; j++) {
- ss = &(ap_scoreboard_image->table[i][j]);
- if (ss->key[0] != '\0') {
- apr_table_add(array_slot->data, ss->key, ss->value);
- }
- else {
- break;
- }
- }
- }
- return server_status;
-}
+++ /dev/null
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#ifndef APACHE_SCOREBOARD_H
-#define APACHE_SCOREBOARD_H
-#include <pthread.h>
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifdef TPF
-#include <time.h>
-#else
-#include <sys/times.h>
-#endif /* TPF */
-
-#include "mpm_default.h" /* For HARD_.*_LIMIT */
-
-/* The generic shared memory chunk code */
-void reinit_scoreboard(apr_pool_t *p);
-
-AP_DECLARE(void) reopen_scoreboard(apr_pool_t *p);
-
-/* The stuff for Dexter's status table */
-
-#include "mpm_status.h"
-
-void ap_dexter_set_maintain_connection_status(int flag);
-void ap_dexter_force_reset_connection_status(long conn_id);
-#define KEY_LENGTH 16
-#define VALUE_LENGTH 64
-typedef struct {
- char key[KEY_LENGTH];
- char value[VALUE_LENGTH];
-} status_table_entry;
-
-#define STATUSES_PER_CONNECTION 10
-
-typedef struct {
- status_table_entry
- table[HARD_SERVER_LIMIT*HARD_THREAD_LIMIT][STATUSES_PER_CONNECTION];
-} scoreboard;
-
-#define SCOREBOARD_SIZE sizeof(scoreboard)
-
-AP_DECLARE_DATA extern const char *ap_scoreboard_fname;
-
-apr_status_t ap_cleanup_shared_mem(void *d);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* !APACHE_SCOREBOARD_H */
LTLIBRARY_NAME = libperchild.la
-LTLIBRARY_SOURCES = perchild.c scoreboard.c
+LTLIBRARY_SOURCES = perchild.c
include $(top_srcdir)/build/ltlib.mk
LTLIBRARY_NAME = libmpmt_beos.la
-LTLIBRARY_SOURCES = mpmt_beos.c scoreboard.c poll.c
+LTLIBRARY_SOURCES = mpmt_beos.c poll.c
include $(top_srcdir)/build/ltlib.mk
+++ /dev/null
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#include "httpd.h"
-#include "http_log.h"
-#include "http_main.h"
-#include "http_core.h"
-#include "http_config.h"
-#include "mpm_status.h"
-#include "beosd.h"
-#include "http_conf_globals.h"
-#include "mpmt_beos.h"
-#include "mpm.h" /* includes scoreboard.h */
-
-scoreboard *ap_scoreboard_image = NULL;
-extern apr_pool_t * pconf;
-extern int ap_max_daemons_limit;
-static int maintain_connection_status = 1;
-
-void reinit_scoreboard(apr_pool_t *p)
-{
- ap_assert(!ap_scoreboard_image);
- ap_scoreboard_image = (scoreboard *) malloc(SCOREBOARD_SIZE);
- if (ap_scoreboard_image == NULL) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "Ouch! Out of memory reiniting scoreboard!");
- }
- memset(ap_scoreboard_image, 0, SCOREBOARD_SIZE);
-}
-
-void cleanup_scoreboard(void)
-{
- ap_assert(ap_scoreboard_image);
- free(ap_scoreboard_image);
- ap_scoreboard_image = NULL;
-}
-
-AP_DECLARE(int) ap_exists_scoreboard_image(void)
-{
- return (ap_scoreboard_image ? 1 : 0);
-}
-
-
-void ap_update_connection_status(long conn_id, const char *key,
- const char *value)
-{
- int i = 0;
- status_table_entry *ss;
-
- if (!maintain_connection_status) return;
- while (i < STATUSES_PER_CONNECTION) {
- ss = &(ap_scoreboard_image->table[conn_id][i]);
- if (ss->key[0] == '\0') {
- break;
- }
- if (0 == strcmp(ss->key, key)) {
- apr_cpystrn(ss->value, value, VALUE_LENGTH);
- return;
- }
- i++;
- }
- if (i >= STATUSES_PER_CONNECTION) {
- return;
- }
- apr_cpystrn(ss->key, key, KEY_LENGTH);
- apr_cpystrn(ss->value, value, VALUE_LENGTH);
- return;
-}
-
-void ap_reset_connection_status(long conn_id)
-{
- if (maintain_connection_status) {
- ap_mpmt_beos_force_reset_connection_status(conn_id);
- }
-}
-
-void ap_mpmt_beos_set_maintain_connection_status(int flag) {
- maintain_connection_status = flag;
- return;
-}
-
-void ap_mpmt_beos_force_reset_connection_status(long conn_id)
-{
- int i;
-
- for (i = 0; i < STATUSES_PER_CONNECTION; i++) {
- ap_scoreboard_image->table[conn_id][i].key[0] = '\0';
- }
-}
-
-const char *ap_get_connection_status(long conn_id, const char *key)
-{
- int i = 0;
- status_table_entry *ss;
-
- if (!maintain_connection_status) return "";
- while (i < STATUSES_PER_CONNECTION) {
- ss = &(ap_scoreboard_image->table[conn_id][i]);
- if (ss->key[0] == '\0') {
- break;
- }
- if (0 == strcmp(ss->key, key)) {
- return ss->value;
- }
- }
-
- return NULL;
-}
-
-apr_array_header_t *ap_get_connections(apr_pool_t *p)
-{
- int i;
- apr_array_header_t *connection_list;
- long *array_slot;
-
- connection_list = apr_make_array(p, 0, sizeof(long));
- for (i = 0; i < ap_max_daemons_limit * HARD_THREAD_LIMIT; i++) {
- if (ap_scoreboard_image->table[i][0].key[0] != '\0') {
- array_slot = apr_push_array(connection_list);
- *array_slot = i;
- }
- }
- return connection_list;
-}
-
-apr_array_header_t *ap_get_connection_keys(apr_pool_t *p, long conn_id)
-{
- int i = 0;
- status_table_entry *ss;
- apr_array_header_t *key_list;
- char **array_slot;
-
- key_list = apr_make_array(p, 0, KEY_LENGTH * sizeof(char));
- while (i < STATUSES_PER_CONNECTION) {
- ss = &(ap_scoreboard_image->table[conn_id][i]);
- if (ss->key[0] == '\0') {
- break;
- }
- array_slot = apr_push_array(key_list);
- *array_slot = apr_pstrdup(p, ss->key);
- i++;
- }
- return key_list;
-}
-
-apr_array_header_t *ap_get_status_table(apr_pool_t *p)
-{
- int i, j;
- apr_array_header_t *server_status;
- ap_status_table_row_t *array_slot;
- status_table_entry *ss;
-
- server_status = apr_make_array(p, 0, sizeof(ap_status_table_row_t));
-
- for (i = 0; i < ap_max_daemons_limit * HARD_THREAD_LIMIT; i++) {
- if (ap_scoreboard_image->table[i][0].key[0] == '\0')
- continue;
- array_slot = apr_push_array(server_status);
- array_slot->data = apr_make_table(p, 0);
- array_slot->conn_id = i;
-
- for (j = 0; j < STATUSES_PER_CONNECTION; j++) {
- ss = &(ap_scoreboard_image->table[i][j]);
- if (ss->key[0] != '\0') {
- apr_table_add(array_slot->data, ss->key, ss->value);
- }
- else {
- break;
- }
- }
- }
- return server_status;
-}
+++ /dev/null
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#ifndef MPMT_BEOS_SCOREBOARD_H
-#define MPMT_BEOS_SCOREBOARD_H
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-#include <sys/times.h>
-#include "mpm_default.h" /* For HARD_.*_LIMIT */
-
-AP_DECLARE(int) ap_exists_scoreboard_image(void);
-void reinit_scoareboard(apr_pool_t *p);
-void cleanup_scoreboard(void);
-void ap_mpmt_beos_set_maintain_connection_status(int flag);
-void ap_mpmt_beos_force_reset_connection_status(long conn_id);
-void reinit_scoreboard(apr_pool_t *p);
-void update_scoreboard_global(void);
-AP_DECLARE(int) find_child_by_pid(int pid);
-int ap_update_child_status(int child_num, int thread_num, int status, request_rec *r);
-void ap_time_process_request(int child_num, int thread_num, int status);
-
-/* Add support for connection table functions */
-
-#define KEY_LENGTH 16
-#define VALUE_LENGTH 64
-
-typedef struct {
- char key[KEY_LENGTH];
- char value[VALUE_LENGTH];
-} status_table_entry;
-
-#define STATUSES_PER_CONNECTION 10
-
-typedef struct {
- status_table_entry
- table[HARD_SERVER_LIMIT*HARD_THREAD_LIMIT][STATUSES_PER_CONNECTION];
-} scoreboard;
-
-#define SCOREBOARD_SIZE sizeof(scoreboard)
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* !MPMT_BEOS_SCOREBOARD_H */
LTLIBRARY_NAME = libmpmt_pthread.la
-LTLIBRARY_SOURCES = mpmt_pthread.c scoreboard.c
+LTLIBRARY_SOURCES = mpmt_pthread.c
include $(top_srcdir)/build/ltlib.mk
APACHE_MPM_PTHREAD
-dnl Obsolete scoreboard code uses this.
- AC_CHECK_HEADERS(sys/times.h)
- AC_CHECK_FUNCS(times)
fi
extern int ap_threads_per_child;
extern int ap_max_requests_per_child;
-extern int ap_extended_status;
extern int ap_max_daemons_limit;
extern unsigned int ap_my_pid;
extern server_rec *ap_server_conf;
#ifndef APACHE_MPM_DEFAULT_H
#define APACHE_MPM_DEFAULT_H
+#define AP_ID_FROM_CHILD_THREAD(c, t) ((c * HARD_SERVER_LIMIT) + HARD_THREAD_LIMIT)
+#define AP_CHILD_THREAD_FROM_ID(i) (i / HARD_SERVER_LIMIT), (i % HARD_THREAD_LIMIT)
+
/* Number of servers to spawn off by default --- also, if fewer than
* this free when the caretaker checks, it will spawn more.
*/
int ap_threads_per_child=0; /* Worker threads per child */
int ap_max_requests_per_child=0;
static const char *ap_pid_fname=NULL;
-AP_DECLARE_DATA const char *ap_scoreboard_fname=NULL;
static int ap_daemons_to_start=0;
static int min_spare_threads=0;
static int max_spare_threads=0;
static int ap_daemons_limit=0;
-static time_t ap_restart_time=0;
-AP_DECLARE_DATA int ap_extended_status = 0;
static int workers_may_exit = 0;
static int requests_this_child;
static int num_listensocks = 0;
{
int i, j;
int idle_thread_count;
- thread_score *ss;
+ short_score *ss;
time_t now = 0;
int free_length;
int free_slots[MAX_SPAWN_RATE];
/* non-fatal death... note that it's gone in the scoreboard. */
child_slot = find_child_by_pid(&pid);
if (child_slot >= 0) {
- ap_mpmt_pthread_force_reset_connection_status(child_slot);
for (i = 0; i < ap_threads_per_child; i++)
ap_update_child_status(child_slot, i, SERVER_DEAD, (request_rec *) NULL);
LTLIBRARY_NAME = libperchild.la
-LTLIBRARY_SOURCES = perchild.c scoreboard.c
+LTLIBRARY_SOURCES = perchild.c
include $(top_srcdir)/build/ltlib.mk
+++ /dev/null
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#include "apr_strings.h"
-#include "ap_config.h"
-#include "httpd.h"
-#include "http_log.h"
-#include "http_main.h"
-#include "http_core.h"
-#include "http_config.h"
-#include "unixd.h"
-#include "http_conf_globals.h"
-#include "mpm_status.h"
-#include "scoreboard.h"
-#include "mpm.h" /* for ap_max_daemons_limit */
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-static scoreboard *ap_scoreboard_image = NULL;
-
-/*****************************************************************
- *
- * Dealing with the scoreboard... a lot of these variables are global
- * only to avoid getting clobbered by the longjmp() that happens when
- * a hard timeout expires...
- *
- * We begin with routines which deal with the file itself...
- */
-
-#if APR_HAS_SHARED_MEMORY
-#include "apr_shmem.h"
-
-static apr_shmem_t *scoreboard_shm = NULL;
-
-apr_status_t ap_cleanup_shared_mem(void *d)
-{
- apr_shm_free(scoreboard_shm, ap_scoreboard_image);
- ap_scoreboard_image = NULL;
- apr_shm_destroy(scoreboard_shm);
- return APR_SUCCESS;
-}
-
-static void setup_shared_mem(apr_pool_t *p)
-{
- char buf[512];
- char errmsg[120];
- const char *fname;
- apr_status_t rv;
-
- fname = ap_server_root_relative(p, ap_scoreboard_fname);
- rv = apr_shm_init(&scoreboard_shm, SCOREBOARD_SIZE, fname, p);
- if (rv != APR_SUCCESS) {
- apr_snprintf(buf, sizeof(buf), "%s: could not open(create) scoreboard: %s",
- ap_server_argv0, apr_strerror(rv, errmsg, sizeof errmsg));
- fprintf(stderr, "%s\n", buf);
- exit(APEXIT_INIT);
- }
- ap_scoreboard_image = apr_shm_malloc(scoreboard_shm, SCOREBOARD_SIZE);
- if (ap_scoreboard_image == NULL) {
- apr_snprintf(buf, sizeof(buf), "%s: cannot allocate scoreboard",
- ap_server_argv0);
- perror(buf); /* o.k. since MM sets errno */
- apr_shm_destroy(scoreboard_shm);
- exit(APEXIT_INIT);
- }
- apr_register_cleanup(p, NULL, ap_cleanup_shared_mem, apr_null_cleanup);
-}
-
-void reinit_scoreboard(apr_pool_t *p)
-{
- if (ap_scoreboard_image == NULL) {
- setup_shared_mem(p);
- }
- memset(ap_scoreboard_image, 0, SCOREBOARD_SIZE);
-}
-#endif /* APR_SHARED_MEM */
-
-/****
- * Above code is shmem code. Below code is interacting with the shmem
- ****/
-
-static int maintain_connection_status = 1;
-
-void ap_perchild_set_maintain_connection_status(int flag) {
- maintain_connection_status = flag;
- return;
-}
-
-/* Useful to erase the status of children that might be from previous
- * generations */
-void ap_perchild_force_reset_connection_status(long conn_id)
-{
- int i;
-
- for (i = 0; i < STATUSES_PER_CONNECTION; i++) {
- ap_scoreboard_image->table[conn_id][i].key[0] = '\0';
- }
-}
-
-void ap_reset_connection_status(long conn_id)
-{
- if (maintain_connection_status) {
- ap_perchild_force_reset_connection_status(conn_id);
- }
-}
-
-/* Don't mess with the string you get back from this function */
-const char *ap_get_connection_status(long conn_id, const char *key)
-{
- int i = 0;
- status_table_entry *ss;
-
- if (!maintain_connection_status) return "";
- while (i < STATUSES_PER_CONNECTION) {
- ss = &(ap_scoreboard_image->table[conn_id][i]);
- if (ss->key[0] == '\0') {
- break;
- }
- if (0 == strcmp(ss->key, key)) {
- return ss->value;
- }
- }
-
- return NULL;
-}
-
-apr_array_header_t *ap_get_connections(apr_pool_t *p)
-{
- int i;
- apr_array_header_t *connection_list;
- long *array_slot;
-
- connection_list = apr_make_array(p, 0, sizeof(long));
- /* We assume that there is a connection iff it has an entry in the status
- * table. Connections without any status sound problematic to me, so this
- * is probably for the best. - manoj */
- for (i = 0; i < ap_max_daemons_limit*HARD_THREAD_LIMIT; i++) {
- if (ap_scoreboard_image->table[i][0].key[0] != '\0') {
- array_slot = apr_push_array(connection_list);
- *array_slot = i;
- }
- }
- return connection_list;
-}
-
-apr_array_header_t *ap_get_connection_keys(apr_pool_t *p, long conn_id)
-{
- int i = 0;
- status_table_entry *ss;
- apr_array_header_t *key_list;
- char **array_slot;
-
- key_list = apr_make_array(p, 0, KEY_LENGTH * sizeof(char));
- while (i < STATUSES_PER_CONNECTION) {
- ss = &(ap_scoreboard_image->table[conn_id][i]);
- if (ss->key[0] == '\0') {
- break;
- }
- array_slot = apr_push_array(key_list);
- *array_slot = apr_pstrdup(p, ss->key);
- i++;
- }
- return key_list;
-}
-
-/* Note: no effort is made here to prevent multiple threads from messing with
- * a single connection at the same time. ap_update_connection_status should
- * only be called by the thread that owns the connection */
-
-void ap_update_connection_status(long conn_id, const char *key,
- const char *value)
-{
- int i = 0;
- status_table_entry *ss;
-
- if (!maintain_connection_status) return;
- while (i < STATUSES_PER_CONNECTION) {
- ss = &(ap_scoreboard_image->table[conn_id][i]);
- if (ss->key[0] == '\0') {
- break;
- }
- if (0 == strcmp(ss->key, key)) {
- apr_cpystrn(ss->value, value, VALUE_LENGTH);
- return;
- }
- i++;
- }
- /* Not found. Add an entry for this value */
- if (i >= STATUSES_PER_CONNECTION) {
- /* No room. Oh well, not much anyone can do about it. */
- return;
- }
- apr_cpystrn(ss->key, key, KEY_LENGTH);
- apr_cpystrn(ss->value, value, VALUE_LENGTH);
- return;
-}
-
-apr_array_header_t *ap_get_status_table(apr_pool_t *p)
-{
- int i, j;
- apr_array_header_t *server_status;
- ap_status_table_row_t *array_slot;
- status_table_entry *ss;
-
- server_status = apr_make_array(p, 0, sizeof(ap_status_table_row_t));
-
- /* Go ahead and return what's in the connection status table even if we
- * aren't maintaining it. We can at least look at what children from
- * previous generations are up to. */
-
- for (i = 0; i < ap_max_daemons_limit*HARD_THREAD_LIMIT; i++) {
- if (ap_scoreboard_image->table[i][0].key[0] == '\0')
- continue;
- array_slot = apr_push_array(server_status);
- array_slot->data = apr_make_table(p, 0);
- array_slot->conn_id = i;
-
- for (j = 0; j < STATUSES_PER_CONNECTION; j++) {
- ss = &(ap_scoreboard_image->table[i][j]);
- if (ss->key[0] != '\0') {
- apr_table_add(array_slot->data, ss->key, ss->value);
- }
- else {
- break;
- }
- }
- }
- return server_status;
-}
+++ /dev/null
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#ifndef APACHE_SCOREBOARD_H
-#define APACHE_SCOREBOARD_H
-#include <pthread.h>
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifdef TPF
-#include <time.h>
-#else
-#include <sys/times.h>
-#endif /* TPF */
-
-#include "mpm_default.h" /* For HARD_.*_LIMIT */
-
-/* The generic shared memory chunk code */
-void reinit_scoreboard(apr_pool_t *p);
-
-AP_DECLARE(void) reopen_scoreboard(apr_pool_t *p);
-
-/* The stuff for perchild's status table */
-
-#include "mpm_status.h"
-
-void ap_perchild_set_maintain_connection_status(int flag);
-void ap_perchild_force_reset_connection_status(long conn_id);
-#define KEY_LENGTH 16
-#define VALUE_LENGTH 64
-typedef struct {
- char key[KEY_LENGTH];
- char value[VALUE_LENGTH];
-} status_table_entry;
-
-#define STATUSES_PER_CONNECTION 10
-
-typedef struct {
- status_table_entry
- table[HARD_SERVER_LIMIT*HARD_THREAD_LIMIT][STATUSES_PER_CONNECTION];
-} scoreboard;
-
-#define SCOREBOARD_SIZE sizeof(scoreboard)
-
-AP_DECLARE_DATA extern const char *ap_scoreboard_fname;
-apr_status_t ap_cleanup_shared_mem(void *d);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* !APACHE_SCOREBOARD_H */
APACHE_FAST_OUTPUT(server/mpm/$MPM_NAME/Makefile)
-dnl Obsolete scoreboard code uses this.
- AC_CHECK_HEADERS(sys/times.h)
- AC_CHECK_FUNCS(times)
fi
#define MPM_CHILD_PID(i) (ap_scoreboard_image->parent[i].pid)
#define MPM_NOTE_CHILD_KILLED(i) (MPM_CHILD_PID(i) = 0)
+extern int ap_threads_per_child;
extern int ap_max_daemons_limit;
extern scoreboard *ap_scoreboard_image;
extern server_rec *ap_server_conf;
#ifndef APACHE_MPM_DEFAULT_H
#define APACHE_MPM_DEFAULT_H
+#define AP_ID_FROM_CHILD_THREAD(c, t) c
+#define AP_CHILD_THREAD_FROM_ID(i) i, 0
+
+
/* Number of servers to spawn off by default --- also, if fewer than
* this free when the caretaker checks, it will spawn more.
*/
#define HARD_SERVER_LIMIT 256
#endif
+#ifndef HARD_THREAD_LIMIT
+#define HARD_THREAD_LIMIT 1
+#endif
+
/* File used for accept locking, when we use a file */
#ifndef DEFAULT_LOCKFILE
#define DEFAULT_LOCKFILE "logs/accept.lock"
/* TODO: this is a cobbled together prefork MPM example... it should mostly
* TODO: behave like apache-1.3... here's a short list of things I think
* TODO: need cleaning up still:
- * TODO: - clean up scoreboard stuff when we figure out how to do it in 2.0
*/
#include "apr.h"
#include "ap_config.h"
#include "httpd.h"
#include "mpm_default.h"
-#include "mpm_status.h"
#include "http_main.h"
#include "http_log.h"
#include "http_config.h"
/* config globals */
+int ap_threads_per_child=0; /* Worker threads per child */
static int ap_max_requests_per_child=0;
static const char *ap_pid_fname=NULL;
static apr_lock_t *accept_lock;
-static const char *ap_scoreboard_fname=NULL;
static const char *ap_lock_fname;
static int ap_daemons_to_start=0;
static int ap_daemons_min_free=0;
static int ap_daemons_max_free=0;
static int ap_daemons_limit=0;
-static time_t ap_restart_time=0;
static int ap_extended_status = 0;
-static int maintain_connection_status = 1;
/*
* The max child slot ever assigned, preserved across restarts. Necessary
char tpf_server_name[INETD_SERVNAME_LENGTH+1];
#endif /* TPF */
-AP_DECLARE_DATA scoreboard *ap_scoreboard_image = NULL;
-static new_scoreboard *ap_new_scoreboard_image = NULL;
-
#ifdef GPROF
/*
* change directory for gprof to plop the gmon.out file
#define SAFE_ACCEPT(stmt) do {stmt;} while(0)
#endif
-#if APR_HAS_SHARED_MEMORY
-#include "apr_shmem.h"
-
-static apr_shmem_t *scoreboard_shm = NULL;
-static apr_shmem_t *status_shm = NULL;
-
-static apr_status_t cleanup_shared_mem(void *d)
-{
- apr_shm_free(scoreboard_shm, ap_scoreboard_image);
- apr_shm_free(status_shm, ap_new_scoreboard_image);
- ap_scoreboard_image = NULL;
- ap_new_scoreboard_image = NULL;
- apr_shm_destroy(scoreboard_shm);
- apr_shm_destroy(status_shm);
- return APR_SUCCESS;
-}
-
-static void setup_shared_mem(apr_pool_t *p)
-{
- char buf[512];
- char errmsg[120];
- const char *fname;
- apr_status_t rv;
-
- fname = ap_server_root_relative(p, ap_scoreboard_fname);
- rv = apr_shm_init(&scoreboard_shm, SCOREBOARD_SIZE, fname, p);
- if (rv != APR_SUCCESS) {
- apr_snprintf(buf, sizeof(buf), "%s: could not open(create) scoreboard: %s",
- ap_server_argv0, apr_strerror(rv, errmsg, sizeof errmsg));
- fprintf(stderr, "%s\n", buf);
- exit(APEXIT_INIT);
- }
- ap_scoreboard_image = apr_shm_malloc(scoreboard_shm, SCOREBOARD_SIZE);
- rv = apr_shm_init(&status_shm, NEW_SCOREBOARD_SIZE, fname, p);
- if (rv != APR_SUCCESS) {
- apr_snprintf(buf, sizeof(buf), "%s: could not open(create) scoreboard: %s",
- ap_server_argv0, apr_strerror(rv, errmsg, sizeof errmsg));
- fprintf(stderr, "%s\n", buf);
- exit(APEXIT_INIT);
- }
- ap_new_scoreboard_image = apr_shm_malloc(status_shm, NEW_SCOREBOARD_SIZE);
- if (ap_scoreboard_image == NULL || ap_new_scoreboard_image == NULL) {
- apr_snprintf(buf, sizeof(buf), "%s: cannot allocate scoreboard",
- ap_server_argv0);
- perror(buf); /* o.k. since MM sets errno */
- apr_shm_destroy(scoreboard_shm);
- apr_shm_destroy(status_shm);
- exit(APEXIT_INIT);
- }
- apr_register_cleanup(p, NULL, cleanup_shared_mem, apr_null_cleanup);
- ap_scoreboard_image->global.running_generation = 0;
-}
-
-static void reopen_scoreboard(apr_pool_t *p)
-{
-}
-#endif
-
-/* Called by parent process */
-static void reinit_scoreboard(apr_pool_t *p)
-{
- int running_gen = 0;
- if (ap_scoreboard_image)
- running_gen = ap_scoreboard_image->global.running_generation;
-
- if (ap_scoreboard_image == NULL) {
- setup_shared_mem(p);
- }
- memset(ap_scoreboard_image, 0, SCOREBOARD_SIZE);
- ap_scoreboard_image->global.running_generation = running_gen;
-}
-
-
-/* Routines called to deal with the scoreboard image
- * --- note that we do *not* need write locks, since update_child_status
- * only updates a *single* record in place, and only one process writes to
- * a given scoreboard slot at a time (either the child process owning that
- * slot, or the parent, noting that the child has died).
- *
- * As a final note --- setting the score entry to getpid() is always safe,
- * since when the parent is writing an entry, it's only noting SERVER_DEAD
- * anyway.
- */
-apr_inline void ap_sync_scoreboard_image(void)
-{
-#ifdef SCOREBOARD_FILE
- lseek(scoreboard_fd, 0L, 0);
- force_read(scoreboard_fd, ap_scoreboard_image, sizeof(*ap_scoreboard_image))
-;
-#endif
-}
-
-AP_DECLARE(int) ap_exists_scoreboard_image(void)
-{
- return (ap_scoreboard_image ? 1 : 0);
-}
-
AP_DECLARE(int) ap_get_max_daemons(void)
{
return ap_max_daemons_limit;
}
-static apr_inline void put_scoreboard_info(int child_num,
- short_score *new_score_rec)
-{
-#ifdef SCOREBOARD_FILE
- lseek(scoreboard_fd, (long) child_num * sizeof(short_score), 0);
- force_write(scoreboard_fd, new_score_rec, sizeof(short_score));
-#endif
-}
-
-int ap_update_child_status(int child_num, int status, request_rec *r)
-{
- int old_status;
- short_score *ss;
-
- if (child_num < 0)
- return -1;
-
- ap_check_signals();
-
- ss = &ap_scoreboard_image->servers[child_num];
- old_status = ss->status;
- ss->status = status;
-
- if (ap_extended_status) {
- if (status == SERVER_READY || status == SERVER_DEAD) {
- /*
- * Reset individual counters
- */
- if (status == SERVER_DEAD) {
- ss->my_access_count = 0L;
- ss->my_bytes_served = 0L;
- }
- ss->conn_count = (unsigned short) 0;
- ss->conn_bytes = (unsigned long) 0;
- }
- if (r) {
- conn_rec *c = r->connection;
- apr_cpystrn(ss->client, ap_get_remote_host(c, r->per_dir_config,
- REMOTE_NOLOOKUP), sizeof(ss->client));
- if (r->the_request == NULL) {
- apr_cpystrn(ss->request, "NULL", sizeof(ss->request));
- } else if (r->parsed_uri.password == NULL) {
- apr_cpystrn(ss->request, r->the_request, sizeof(ss->request));
- } else {
- /* Don't reveal the password in the server-status view */
- apr_cpystrn(ss->request, apr_pstrcat(r->pool, r->method, " ",
- ap_unparse_uri_components(r->pool, &r->parsed_uri, UNP_OMITPASSWORD),
- r->assbackwards ? NULL : " ", r->protocol, NULL),
- sizeof(ss->request));
- }
- ss->vhostrec = r->server;
- }
- }
- if (status == SERVER_STARTING && r == NULL) {
- /* clean up the slot's vhostrec pointer (maybe re-used)
- * and mark the slot as belonging to a new generation.
- */
- ss->vhostrec = NULL;
- ap_scoreboard_image->parent[child_num].generation = ap_my_generation;
-#ifdef SCOREBOARD_FILE
- lseek(scoreboard_fd, XtOffsetOf(scoreboard, parent[child_num]), 0);
- force_write(scoreboard_fd, &ap_scoreboard_image->parent[child_num],
- sizeof(parent_score));
-#endif
- }
- put_scoreboard_info(child_num, ss);
-
- return old_status;
-}
-
-static void update_scoreboard_global(void)
-{
-#ifdef SCOREBOARD_FILE
- lseek(scoreboard_fd,
- (char *) &ap_scoreboard_image->global -(char *) ap_scoreboard_image, 0);
- force_write(scoreboard_fd, &ap_scoreboard_image->global,
- sizeof ap_scoreboard_image->global);
-#endif
-}
-
-void ap_time_process_request(int child_num, int status)
-{
- short_score *ss;
-
- if (child_num < 0)
- return;
-
- ap_sync_scoreboard_image();
- ss = &ap_scoreboard_image->servers[child_num];
-
- if (status == START_PREQUEST) {
- ss->start_time = apr_now();
- }
- else if (status == STOP_PREQUEST) {
- ss->stop_time = apr_now();
- }
-
- put_scoreboard_info(child_num, ss);
-}
-
-/*
-static void increment_counts(int child_num, request_rec *r)
-{
- short_score *ss;
-
- ap_sync_scoreboard_image();
- ss = &ap_scoreboard_image->servers[child_num];
-
-#ifdef HAVE_TIMES
- times(&ss->times);
-#endif
- ss->access_count++;
- ss->my_access_count++;
- ss->conn_count++;
- ss->bytes_served += r->bytes_sent;
- ss->my_bytes_served += r->bytes_sent;
- ss->conn_bytes += r->bytes_sent;
-
- put_scoreboard_info(child_num, ss);
-}
-*/
-
-static int find_child_by_pid(apr_proc_t *pid)
-{
- int i;
-
- for (i = 0; i < ap_max_daemons_limit; ++i)
- if (ap_scoreboard_image->parent[i].pid == pid->pid)
- return i;
-
- return -1;
-}
-
#if defined(NEED_WAITPID)
/*
Systems without a real waitpid sometimes lose a child's exit while waiting
for (n = 0; n < ap_max_daemons_limit; ++n) {
ap_sync_scoreboard_image();
- if (ap_scoreboard_image->servers[n].status != SERVER_DEAD &&
+ if (ap_scoreboard_image->servers[n][0].status != SERVER_DEAD &&
kill((pid = ap_scoreboard_image->parent[n].pid), 0) == -1) {
- ap_update_child_status(n, SERVER_DEAD, NULL);
+ ap_update_child_status(AP_CHILD_THREAD_FROM_ID(n), SERVER_DEAD, NULL);
/* just mark it as having a successful exit status */
memset(status, 0, sizeof(apr_wait_t));
return(pid);
}
restart_pending = 1;
if ((is_graceful = (sig == SIGWINCH))) {
- apr_kill_cleanup(pconf, NULL, cleanup_shared_mem);
+ apr_kill_cleanup(pconf, NULL, ap_cleanup_shared_mem);
}
}
ap_child_init_hook(pchild, ap_server_conf);
- (void) ap_update_child_status(my_child_num, SERVER_READY, (request_rec *) NULL);
+ (void) ap_update_child_status(AP_CHILD_THREAD_FROM_ID(my_child_num), SERVER_READY, (request_rec *) NULL);
apr_signal(SIGHUP, just_die);
apr_signal(SIGTERM, just_die);
clean_child_exit(0);
}
- (void) ap_update_child_status(my_child_num, SERVER_READY, (request_rec *) NULL);
+ (void) ap_update_child_status(AP_CHILD_THREAD_FROM_ID(my_child_num), SERVER_READY, (request_rec *) NULL);
/*
* Wait for an acceptable connection to arrive.
ap_sock_disable_nagle(csd);
- (void) ap_update_child_status(my_child_num, SERVER_BUSY_READ,
+ (void) ap_update_child_status(AP_CHILD_THREAD_FROM_ID(my_child_num), SERVER_BUSY_READ,
(request_rec *) NULL);
current_conn = ap_new_connection(ptrans, ap_server_conf, csd,
child_main(slot);
}
- (void) ap_update_child_status(slot, SERVER_STARTING, (request_rec *) NULL);
+ (void) ap_update_child_status(AP_CHILD_THREAD_FROM_ID(slot), SERVER_STARTING, (request_rec *) NULL);
#ifdef _OSD_POSIX
/* fork didn't succeed. Fix the scoreboard or else
* it will say SERVER_STARTING forever and ever
*/
- (void) ap_update_child_status(slot, SERVER_DEAD, (request_rec *) NULL);
+ (void) ap_update_child_status(AP_CHILD_THREAD_FROM_ID(slot), SERVER_DEAD, (request_rec *) NULL);
/* In case system resources are maxxed out, we don't want
Apache running away with the CPU trying to fork over and
time_t now = time(0);
for (i = 0; number_to_start && i < ap_daemons_limit; ++i) {
- if (ap_scoreboard_image->servers[i].status != SERVER_DEAD) {
+ if (ap_scoreboard_image->servers[i][0].status != SERVER_DEAD) {
continue;
}
if (make_child(ap_server_conf, i, now) < 0) {
if (i >= ap_max_daemons_limit && free_length == idle_spawn_rate)
break;
- ss = &ap_scoreboard_image->servers[i];
+ ss = &ap_scoreboard_image->servers[i][0];
status = ss->status;
if (status == SERVER_DEAD) {
/* try to keep children numbers as low as possible */
return 0;
}
-/* Useful to erase the status of children that might be from previous
- * generations */
-static void ap_prefork_force_reset_connection_status(long conn_id)
-{
- int i;
-
- for (i = 0; i < STATUSES_PER_CONNECTION; i++) {
- ap_new_scoreboard_image->table[conn_id][i].key[0] = '\0';
- } }
-
-void ap_reset_connection_status(long conn_id)
-{
- if (maintain_connection_status) {
- ap_prefork_force_reset_connection_status(conn_id);
- }
-}
-
/*****************************************************************
* Executive routines.
*/
ap_sync_scoreboard_image();
child_slot = find_child_by_pid(&pid);
if (child_slot >= 0) {
- ap_prefork_force_reset_connection_status(child_slot);
- (void) ap_update_child_status(child_slot, SERVER_DEAD,
+ (void) ap_update_child_status(AP_CHILD_THREAD_FROM_ID(child_slot), SERVER_DEAD,
(request_rec *) NULL);
if (remaining_children_to_start
&& child_slot < ap_daemons_limit) {
*/
ap_sync_scoreboard_image();
for (i = 0; i < ap_daemons_limit; ++i) {
- if (ap_scoreboard_image->servers[i].status != SERVER_DEAD) {
- ap_scoreboard_image->servers[i].status = SERVER_GRACEFUL;
+ if (ap_scoreboard_image->servers[i][0].status != SERVER_DEAD) {
+ ap_scoreboard_image->servers[i][0].status = SERVER_GRACEFUL;
}
}
#endif
return NULL;
}
-/* Stub functions until this MPM supports the connection status API */
-/* Don't mess with the string you get back from this function */
-const char *ap_get_connection_status(long conn_id, const char *key)
-{
- int i = 0;
- status_table_entry *ss;
-
- if (!maintain_connection_status) return "";
- while (i < STATUSES_PER_CONNECTION) {
- ss = &(ap_new_scoreboard_image->table[conn_id][i]);
- if (ss->key[0] == '\0') {
- break;
- }
- if (0 == strcmp(ss->key, key)) {
- return ss->value;
- }
- }
-
- return NULL;
-}
-
-apr_array_header_t *ap_get_connections(apr_pool_t *p)
-{
- int i;
- apr_array_header_t *connection_list;
- long *array_slot;
-
- connection_list = apr_make_array(p, 0, sizeof(long));
- /* We assume that there is a connection iff it has an entry in the status
- * table. Connections without any status sound problematic to me, so this
- * is probably for the best. - manoj */
- for (i = 0; i < ap_max_daemons_limit; i++) {
- if (ap_new_scoreboard_image->table[i][0].key[0] != '\0') {
- array_slot = apr_push_array(connection_list);
- *array_slot = i;
- }
- }
- return connection_list;
-}
-
-apr_array_header_t *ap_get_connection_keys(apr_pool_t *p, long conn_id)
-{
- int i = 0;
- status_table_entry *ss;
- apr_array_header_t *key_list;
- char **array_slot;
-
- key_list = apr_make_array(p, 0, KEY_LENGTH * sizeof(char));
- while (i < STATUSES_PER_CONNECTION) {
- ss = &(ap_new_scoreboard_image->table[conn_id][i]);
- if (ss->key[0] == '\0') {
- break;
- }
- array_slot = apr_push_array(key_list);
- *array_slot = apr_pstrdup(p, ss->key);
- i++;
- }
- return key_list;
-}
-
-/* Note: no effort is made here to prevent multiple threads from messing with
- * a single connection at the same time. ap_update_connection_status should
- * only be called by the thread that owns the connection */
-
-void ap_update_connection_status(long conn_id, const char *key,
- const char *value)
-{
- int i = 0;
- status_table_entry *ss;
-
- if (!maintain_connection_status) return;
- while (i < STATUSES_PER_CONNECTION) {
- ss = &(ap_new_scoreboard_image->table[conn_id][i]);
- if (ss->key[0] == '\0') {
- break;
- }
- if (0 == strcmp(ss->key, key)) {
- apr_cpystrn(ss->value, value, VALUE_LENGTH);
- return;
- }
- i++;
- }
- /* Not found. Add an entry for this value */
- if (i >= STATUSES_PER_CONNECTION) {
- /* No room. Oh well, not much anyone can do about it. */
- return;
- }
- apr_cpystrn(ss->key, key, KEY_LENGTH);
- apr_cpystrn(ss->value, value, VALUE_LENGTH);
- return;
-}
-
-apr_array_header_t *ap_get_status_table(apr_pool_t *p)
-{
- int i, j;
- apr_array_header_t *server_status;
- ap_status_table_row_t *array_slot;
- status_table_entry *ss;
-
- server_status = apr_make_array(p, 0, sizeof(ap_status_table_row_t));
-
- /* Go ahead and return what's in the connection status table even if we
- * aren't maintaining it. We can at least look at what children from
- * previous generations are up to. */
-
- for (i = 0; i < ap_max_daemons_limit; i++) {
- if (ap_new_scoreboard_image->table[i][0].key[0] == '\0')
- continue;
- array_slot = apr_push_array(server_status);
- array_slot->data = apr_make_table(p, 0);
- array_slot->conn_id = i;
-
- for (j = 0; j < STATUSES_PER_CONNECTION; j++) {
- ss = &(ap_new_scoreboard_image->table[i][j]);
- if (ss->key[0] != '\0') {
- apr_table_add(array_slot->data, ss->key, ss->value);
- }
- else {
- break;
- }
- }
- }
- return server_status;
-}
-
static const command_rec prefork_cmds[] = {
UNIX_DAEMON_COMMANDS
LISTEN_COMMANDS
+++ /dev/null
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#ifndef APACHE_SCOREBOARD_H
-#define APACHE_SCOREBOARD_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef WIN32
-#ifdef TPF
-#include <time.h>
-#else
-#include <sys/times.h>
-#include <sys/time.h>
-#endif /* TPF */
-#endif
-
-
-/* The optimized timeout code only works if we're not using a scoreboard file
- */
-#if defined(AP_USE_MEM_BASED_SCOREBOARD)
-#define OPTIMIZE_TIMEOUTS
-#endif
-
-/* Scoreboard info on a process is, for now, kept very brief ---
- * just status value and pid (the latter so that the caretaker process
- * can properly update the scoreboard when a process dies). We may want
- * to eventually add a separate set of long_score structures which would
- * give, for each process, the number of requests serviced, and info on
- * the current, or most recent, request.
- *
- * Status values:
- */
-
-#define SERVER_DEAD 0
-#define SERVER_STARTING 1 /* Server Starting up */
-#define SERVER_READY 2 /* Waiting for connection (or accept() lock) */
-#define SERVER_BUSY_READ 3 /* Reading a client request */
-#define SERVER_BUSY_WRITE 4 /* Processing a client request */
-#define SERVER_BUSY_KEEPALIVE 5 /* Waiting for more requests via keepalive */
-#define SERVER_BUSY_LOG 6 /* Logging the request */
-#define SERVER_BUSY_DNS 7 /* Looking up a hostname */
-#define SERVER_GRACEFUL 8 /* server is gracefully finishing request */
-#define SERVER_NUM_STATUS 9 /* number of status settings */
-
-/* A "virtual time" is simply a counter that indicates that a child is
- * making progress. The parent checks up on each child, and when they have
- * made progress it resets the last_rtime element. But when the child hasn't
- * made progress in a time that's roughly timeout_len seconds long, it is
- * sent a SIGALRM.
- *
- * vtime is an optimization that is used only when the scoreboard is in
- * shared memory (it's not easy/feasible to do it in a scoreboard file).
- * The essential observation is that timeouts rarely occur, the vast majority
- * of hits finish before any timeout happens. So it really sucks to have to
- * ask the operating system to set up and destroy alarms many times during
- * a request.
- */
-typedef unsigned vtime_t;
-
-/* Type used for generation indicies. Startup and every restart cause a
- * new generation of children to be spawned. Children within the same
- * generation share the same configuration information -- pointers to stuff
- * created at config time in the parent are valid across children. For
- * example, the vhostrec pointer in the scoreboard below is valid in all
- * children of the same generation.
- *
- * The safe way to access the vhost pointer is like this:
- *
- * short_score *ss = pointer to whichver slot is interesting;
- * parent_score *ps = pointer to whichver slot is interesting;
- * server_rec *vh = ss->vhostrec;
- *
- * if (ps->generation != ap_my_generation) {
- * vh = NULL;
- * }
- *
- * then if vh is not NULL it's valid in this child.
- *
- * This avoids various race conditions around restarts.
- */
-typedef int ap_generation_t;
-
-/* stuff which the children generally write, and the parent mainly reads */
-typedef struct {
-#ifdef OPTIMIZE_TIMEOUTS
- vtime_t cur_vtime; /* the child's current vtime */
- unsigned short timeout_len; /* length of the timeout */
-#endif
- unsigned char status;
- unsigned long access_count;
- unsigned long bytes_served;
- unsigned long my_access_count;
- unsigned long my_bytes_served;
- unsigned long conn_bytes;
- unsigned short conn_count;
- apr_time_t start_time;
- apr_time_t stop_time;
-#ifdef HAVE_TIMES
- struct tms times;
-#endif
-#ifndef OPTIMIZE_TIMEOUTS
- time_t last_used;
-#endif
- char client[32]; /* Keep 'em small... */
- char request[64]; /* We just want an idea... */
- server_rec *vhostrec; /* What virtual host is being accessed? */
- /* SEE ABOVE FOR SAFE USAGE! */
-} short_score;
-
-typedef struct {
- ap_generation_t running_generation; /* the generation of children which
- * should still be serving requests. */
-} global_score;
-
-/* stuff which the parent generally writes and the children rarely read */
-typedef struct {
- pid_t pid;
-#ifdef OPTIMIZE_TIMEOUTS
- time_t last_rtime; /* time(0) of the last change */
- vtime_t last_vtime; /* the last vtime the parent has seen */
-#endif
- ap_generation_t generation; /* generation of this child */
-} parent_score;
-
-typedef struct {
- short_score servers[HARD_SERVER_LIMIT];
- parent_score parent[HARD_SERVER_LIMIT];
- global_score global;
-} scoreboard;
-
-#define KEY_LENGTH 16
-#define VALUE_LENGTH 64
-typedef struct {
- char key[KEY_LENGTH];
- char value[VALUE_LENGTH]; } status_table_entry;
-
-#define STATUSES_PER_CONNECTION 10
-
-typedef struct {
- status_table_entry
- table[HARD_SERVER_LIMIT][STATUSES_PER_CONNECTION];
-} new_scoreboard;
-
-#define SCOREBOARD_SIZE sizeof(scoreboard)
-#define NEW_SCOREBOARD_SIZE sizeof(new_scoreboard)
-#ifdef TPF
-#define SCOREBOARD_NAME "SCOREBRD"
-#define SCOREBOARD_FRAMES SCOREBOARD_SIZE/4095 + 1
-#endif
-
-AP_DECLARE(void) ap_sync_scoreboard_image(void);
-AP_DECLARE(int) ap_exists_scoreboard_image(void);
-
-AP_DECLARE_DATA extern scoreboard *ap_scoreboard_image;
-
-AP_DECLARE_DATA extern ap_generation_t volatile ap_my_generation;
-
-/* for time_process_request() in http_main.c */
-#define START_PREQUEST 1
-#define STOP_PREQUEST 2
-
-int ap_update_child_status(int child_num, int status, request_rec *r);
-void ap_time_process_request(int child_num, int status);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* !APACHE_SCOREBOARD_H */
+++ /dev/null
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#ifndef APACHE_SCOREBOARD_H
-#define APACHE_SCOREBOARD_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifdef HAVE_SYS_TIMES_H
-#include <sys/times.h>
-#endif
-
-/* The optimized timeout code only works if we're not using a scoreboard file
- */
-#if defined(AP_USE_MEM_BASED_SCOREBOARD)
-#define OPTIMIZE_TIMEOUTS
-#endif
-
-/* Scoreboard info on a thread is, for now, kept very brief ---
- * just status value and pid (the latter so that the caretaker thread
- * can properly update the scoreboard when a thread dies). We may want
- * to eventually add a separate set of long_score structures which would
- * give, for each thread, the number of requests serviced, and info on
- * the current, or most recent, request.
- *
- * Status values:
- */
-
-#define SERVER_DEAD 0
-#define SERVER_STARTING 1 /* Server Starting up */
-#define SERVER_READY 2 /* Waiting for connection (or accept() lock) */
-#define SERVER_BUSY_READ 3 /* Reading a client request */
-#define SERVER_BUSY_WRITE 4 /* Processing a client request */
-#define SERVER_BUSY_KEEPALIVE 5 /* Waiting for more requests via keepalive */
-#define SERVER_BUSY_LOG 6 /* Logging the request */
-#define SERVER_BUSY_DNS 7 /* Looking up a hostname */
-#define SERVER_GRACEFUL 8 /* server is gracefully finishing request */
-#define SERVER_NUM_STATUS 9 /* number of status settings */
-
-/* A "virtual time" is simply a counter that indicates that a child is
- * making progress. The parent checks up on each child, and when they have
- * made progress it resets the last_rtime element. But when the child hasn't
- * made progress in a time that's roughly timeout_len seconds long, it is
- * sent a SIGALRM.
- *
- * vtime is an optimization that is used only when the scoreboard is in
- * shared memory (it's not easy/feasible to do it in a scoreboard file).
- * The essential observation is that timeouts rarely occur, the vast majority
- * of hits finish before any timeout happens. So it really sucks to have to
- * ask the operating system to set up and destroy alarms many times during
- * a request.
- */
-typedef unsigned vtime_t;
-
-/* Type used for generation indicies. Startup and every restart cause a
- * new generation of children to be spawned. Children within the same
- * generation share the same configuration information -- pointers to stuff
- * created at config time in the parent are valid across children. For
- * example, the vhostrec pointer in the scoreboard below is valid in all
- * children of the same generation.
- *
- * The safe way to access the vhost pointer is like this:
- *
- * short_score *ss = pointer to whichver slot is interesting;
- * parent_score *ps = pointer to whichver slot is interesting;
- * server_rec *vh = ss->vhostrec;
- *
- * if (ps->generation != ap_my_generation) {
- * vh = NULL;
- * }
- *
- * then if vh is not NULL it's valid in this child.
- *
- * This avoids various race conditions around restarts.
- */
-typedef int ap_generation_t;
-
-/* stuff which the children generally write, and the parent mainly reads */
-typedef struct {
-#ifdef OPTIMIZE_TIMEOUTS
- vtime_t cur_vtime; /* the child's current vtime */
- unsigned short timeout_len; /* length of the timeout */
-#endif
- unsigned char status;
- unsigned long access_count;
- unsigned long bytes_served;
- unsigned long my_access_count;
- unsigned long my_bytes_served;
- unsigned long conn_bytes;
- unsigned short conn_count;
- apr_time_t start_time;
- apr_time_t stop_time;
-#ifdef HAVE_TIMES
- struct tms times;
-#endif
-#ifndef OPTIMIZE_TIMEOUTS
- time_t last_used;
-#endif
- char client[32]; /* Keep 'em small... */
- char request[64]; /* We just want an idea... */
- server_rec *vhostrec; /* What virtual host is being accessed? */
- /* SEE ABOVE FOR SAFE USAGE! */
- int thread_retval;
-} short_score;
-
-typedef struct {
- ap_generation_t running_generation; /* the generation of children which
- * should still be serving requests. */
-} global_score;
-
-/* stuff which the parent generally writes and the children rarely read */
-typedef struct {
- pid_t tid;
-#ifdef OPTIMIZE_TIMEOUTS
- time_t last_rtime; /* time(0) of the last change */
- vtime_t last_vtime; /* the last vtime the parent has seen */
-#endif
- ap_generation_t generation; /* generation of this child */
- int deferred_die;
-} parent_score;
-
-typedef struct {
- short_score servers[HARD_SERVER_LIMIT];
- parent_score parent[HARD_SERVER_LIMIT];
- global_score global;
-} scoreboard;
-
-#define SCOREBOARD_SIZE sizeof(scoreboard)
-#ifdef TPF
-#define SCOREBOARD_NAME "SCOREBRD"
-#define SCOREBOARD_FRAMES SCOREBOARD_SIZE/4095 + 1
-#endif
-
-AP_DECLARE(int) ap_exists_scoreboard_image(void);
-
-AP_DECLARE_DATA extern scoreboard *ap_scoreboard_image;
-
-
-/* for time_process_request() in http_main.c */
-#define START_PREQUEST 1
-#define STOP_PREQUEST 2
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* !APACHE_SCOREBOARD_H */
#include "http_config.h"
#include "unixd.h"
#include "http_conf_globals.h"
-#include "mpm_status.h"
#include "mpm.h"
#include "scoreboard.h"
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
-scoreboard *ap_scoreboard_image = NULL;
-new_scoreboard *ap_new_scoreboard_image = NULL;
-static int maintain_connection_status = 1;
-/*****************************************************************
- *
- * Dealing with the scoreboard... a lot of these variables are global
- * only to avoid getting clobbered by the longjmp() that happens when
- * a hard timeout expires...
- *
- * We begin with routines which deal with the file itself...
- */
+AP_DECLARE_DATA scoreboard *ap_scoreboard_image = NULL;
+AP_DECLARE_DATA const char *ap_scoreboard_fname=NULL;
+AP_DECLARE_DATA int ap_extended_status = 0;
+AP_DECLARE_DATA apr_time_t ap_restart_time = 0;
#if APR_HAS_SHARED_MEMORY
#include "apr_shmem.h"
static apr_shmem_t *scoreboard_shm = NULL;
-static apr_shmem_t *status_shm = NULL;
apr_status_t ap_cleanup_shared_mem(void *d)
{
apr_shm_free(scoreboard_shm, ap_scoreboard_image);
- apr_shm_free(status_shm, ap_new_scoreboard_image);
ap_scoreboard_image = NULL;
- ap_new_scoreboard_image = NULL;
apr_shm_destroy(scoreboard_shm);
- apr_shm_destroy(status_shm);
return APR_SUCCESS;
}
exit(APEXIT_INIT);
}
ap_scoreboard_image = apr_shm_malloc(scoreboard_shm, SCOREBOARD_SIZE);
- rv = apr_shm_init(&status_shm, NEW_SCOREBOARD_SIZE, fname, p);
- if (rv != APR_SUCCESS) {
- apr_snprintf(buf, sizeof(buf), "%s: could not open(create) scoreboard: %s",
- ap_server_argv0, apr_strerror(rv, errmsg, sizeof errmsg));
- fprintf(stderr, "%s\n", buf);
- exit(APEXIT_INIT);
- }
- ap_new_scoreboard_image = apr_shm_malloc(status_shm, NEW_SCOREBOARD_SIZE);
- if (ap_scoreboard_image == NULL || ap_new_scoreboard_image == NULL) {
+ if (ap_scoreboard_image == NULL) {
apr_snprintf(buf, sizeof(buf), "%s: cannot allocate scoreboard",
ap_server_argv0);
perror(buf); /* o.k. since MM sets errno */
apr_shm_destroy(scoreboard_shm);
- apr_shm_destroy(status_shm);
exit(APEXIT_INIT);
}
apr_register_cleanup(p, NULL, ap_cleanup_shared_mem, apr_null_cleanup);
}
static apr_inline void put_scoreboard_info(int child_num, int thread_num,
- thread_score *new_score_rec)
+ short_score *new_score_rec)
{
/* XXX - needs to be fixed to account for threads */
#ifdef SCOREBOARD_FILE
- lseek(scoreboard_fd, (long) child_num * sizeof(thread_score), 0);
- force_write(scoreboard_fd, new_score_rec, sizeof(thread_score));
+ lseek(scoreboard_fd, (long) child_num * sizeof(short_score), 0);
+ force_write(scoreboard_fd, new_score_rec, sizeof(short_score));
#endif
}
void increment_counts(int child_num, int thread_num, request_rec *r)
{
- thread_score *ss;
+ short_score *ss;
ss = &ap_scoreboard_image->servers[child_num][thread_num];
int ap_update_child_status(int child_num, int thread_num, int status, request_rec *r)
{
int old_status;
- thread_score *ss;
+ short_score *ss;
parent_score *ps;
if (child_num < 0)
if ((status == SERVER_READY || status == SERVER_ACCEPTING)
&& old_status == SERVER_STARTING) {
- ss->tid = pthread_self();
+ ss->thread_num = child_num * HARD_SERVER_LIMIT + thread_num;
ps->worker_threads = ap_threads_per_child;
}
void ap_time_process_request(int child_num, int thread_num, int status)
{
- thread_score *ss;
+ short_score *ss;
if (child_num < 0)
return;
put_scoreboard_info(child_num, thread_num, ss);
}
-/* Useful to erase the status of children that might be from previous
- * generations */
-void ap_mpmt_pthread_force_reset_connection_status(long conn_id)
-{
- int i;
-
- for (i = 0; i < STATUSES_PER_CONNECTION; i++) { ap_new_scoreboard_image->table[conn_id][i].key[0] = '\0';
- } }
-
-void ap_reset_connection_status(long conn_id)
-{
- if (maintain_connection_status) {
- ap_mpmt_pthread_force_reset_connection_status(conn_id);
- }
-}
-
-/* Don't mess with the string you get back from this function */
-const char *ap_get_connection_status(long conn_id, const char *key)
-{
- int i = 0;
- status_table_entry *ss;
-
- if (!maintain_connection_status) return "";
- while (i < STATUSES_PER_CONNECTION) { ss = &(ap_new_scoreboard_image->table[conn_id][i]);
- if (ss->key[0] == '\0') { break;
- }
- if (0 == strcmp(ss->key, key)) {
- return ss->value;
- }
- }
-
- return NULL;
-}
-
-apr_array_header_t *ap_get_connections(apr_pool_t *p)
-{
- int i;
- apr_array_header_t *connection_list;
- long *array_slot;
- int max_daemons_limit = ap_get_max_daemons();
-
- connection_list = apr_make_array(p, 0, sizeof(long));
- /* We assume that there is a connection iff it has an entry in the status
- * table. Connections without any status sound problematic to me, so this
- * is probably for the best. - manoj */
- for (i = 0; i < max_daemons_limit*HARD_THREAD_LIMIT; i++) {
- if (ap_new_scoreboard_image->table[i][0].key[0] != '\0') {
- array_slot = apr_push_array(connection_list);
- *array_slot = i;
- }
- }
- return connection_list;
-}
-
-apr_array_header_t *ap_get_connection_keys(apr_pool_t *p, long conn_id)
-{
- int i = 0;
- status_table_entry *ss;
- apr_array_header_t *key_list;
- char **array_slot;
-
- key_list = apr_make_array(p, 0, KEY_LENGTH * sizeof(char));
- while (i < STATUSES_PER_CONNECTION) {
- ss = &(ap_new_scoreboard_image->table[conn_id][i]);
- if (ss->key[0] == '\0') {
- break;
- }
- array_slot = apr_push_array(key_list);
- *array_slot = apr_pstrdup(p, ss->key);
- i++;
- }
- return key_list;
-}
-
-/* Note: no effort is made here to prevent multiple threads from messing with
- * a single connection at the same time. ap_update_connection_status should
- * only be called by the thread that owns the connection */
-
-void ap_update_connection_status(long conn_id, const char *key,
- const char *value)
-{
- int i = 0;
- status_table_entry *ss;
-
- if (!maintain_connection_status) return;
- while (i < STATUSES_PER_CONNECTION) {
- ss = &(ap_new_scoreboard_image->table[conn_id][i]);
- if (ss->key[0] == '\0') { break;
- } if (0 == strcmp(ss->key, key)) {
- apr_cpystrn(ss->value, value, VALUE_LENGTH);
- return;
- }
- i++;
- }
- /* Not found. Add an entry for this value */
- if (i >= STATUSES_PER_CONNECTION) {
- /* No room. Oh well, not much anyone can do about it. */
- return;
- }
- apr_cpystrn(ss->key, key, KEY_LENGTH);
- apr_cpystrn(ss->value, value, VALUE_LENGTH);
- return;
-}
-
-apr_array_header_t *ap_get_status_table(apr_pool_t *p)
-{
- int i, j;
- apr_array_header_t *server_status;
- ap_status_table_row_t *array_slot;
- int max_daemons_limit = ap_get_max_daemons();
- status_table_entry *ss;
-
- server_status = apr_make_array(p, 0, sizeof(ap_status_table_row_t));
-
- /* Go ahead and return what's in the connection status table even if we
- * aren't maintaining it. We can at least look at what children from
- * previous generations are up to. */
-
- for (i = 0; i < max_daemons_limit*HARD_THREAD_LIMIT; i++) {
- if (ap_new_scoreboard_image->table[i][0].key[0] == '\0')
- continue;
- array_slot = apr_push_array(server_status);
- array_slot->data = apr_make_table(p, 0);
- array_slot->conn_id = i;
-
- for (j = 0; j < STATUSES_PER_CONNECTION; j++) {
- ss = &(ap_new_scoreboard_image->table[i][j]);
- if (ss->key[0] != '\0') {
- apr_table_add(array_slot->data, ss->key, ss->value);
- }
- else {
- break;
- }
- }
- }
- return server_status;
-}
-
-