scoreboard.c revision 48ad184bd4e1dcb23fd13b582135a76530ff08c6
2N/A/* ====================================================================
2N/A * The Apache Software License, Version 1.1
2N/A *
2N/A * Copyright (c) 2000 The Apache Software Foundation. All rights
2N/A * reserved.
2N/A *
2N/A * Redistribution and use in source and binary forms, with or without
2N/A * modification, are permitted provided that the following conditions
2N/A * are met:
2N/A *
2N/A * 1. Redistributions of source code must retain the above copyright
2N/A * notice, this list of conditions and the following disclaimer.
2N/A *
2N/A * 2. Redistributions in binary form must reproduce the above copyright
2N/A * notice, this list of conditions and the following disclaimer in
2N/A * the documentation and/or other materials provided with the
2N/A * distribution.
2N/A *
2N/A * 3. The end-user documentation included with the redistribution,
2N/A * if any, must include the following acknowledgment:
2790N/A * "This product includes software developed by the
2790N/A * Apache Software Foundation (http://www.apache.org/)."
5337N/A * Alternately, this acknowledgment may appear in the software itself,
2N/A * if and wherever such third-party acknowledgments normally appear.
2N/A *
2N/A * 4. The names "Apache" and "Apache Software Foundation" must
2N/A * not be used to endorse or promote products derived from this
2N/A * software without prior written permission. For written
2N/A * permission, please contact apache@apache.org.
3817N/A *
2N/A * 5. Products derived from this software may not be called "Apache",
2N/A * nor may "Apache" appear in their name, without prior written
2N/A * permission of the Apache Software Foundation.
59N/A *
59N/A * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
2N/A * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2N/A * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2N/A * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
2N/A * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26N/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26N/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
181N/A * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26N/A * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
4811N/A * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
4811N/A * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
4811N/A * SUCH DAMAGE.
3739N/A * ====================================================================
3739N/A *
3739N/A * This software consists of voluntary contributions made by many
3739N/A * individuals on behalf of the Apache Software Foundation. For more
3739N/A * information on the Apache Software Foundation, please see
3739N/A * <http://www.apache.org/>.
3739N/A *
3739N/A * Portions of this software are based upon public domain software
3817N/A * originally written at the National Center for Supercomputing Applications,
3817N/A * University of Illinois, Urbana-Champaign.
26N/A */
26N/A
26N/A#include "apr_strings.h"
26N/A#include "ap_config.h"
26N/A#include "httpd.h"
26N/A#include "http_log.h"
26N/A#include "http_main.h"
700N/A#include "http_core.h"
700N/A#include "http_config.h"
26N/A#include "unixd.h"
26N/A#include "http_conf_globals.h"
26N/A#include "mpm_status.h"
1498N/A#include "scoreboard.h"
1498N/A#include "mpm.h" /* for ap_max_daemons_limit */
26N/A#ifdef HAVE_SYS_TYPES_H
1498N/A#include <sys/types.h>
151N/A#endif
206N/A
26N/Astatic scoreboard *ap_scoreboard_image = NULL;
26N/A
6607N/A/*****************************************************************
26N/A *
26N/A * Dealing with the scoreboard... a lot of these variables are global
26N/A * only to avoid getting clobbered by the longjmp() that happens when
3998N/A * a hard timeout expires...
2818N/A *
2830N/A * We begin with routines which deal with the file itself...
3127N/A */
3998N/A
5745N/A#if APR_HAS_SHARED_MEMORY
5745N/A#include "apr_shmem.h"
26N/A
3294N/Astatic ap_shmem_t *scoreboard_shm = NULL;
26N/A
2N/Astatic ap_status_t cleanup_shared_mem(void *d)
4747N/A{
4437N/A ap_shm_free(scoreboard_shm, ap_scoreboard_image);
4437N/A ap_scoreboard_image = NULL;
4488N/A ap_shm_destroy(scoreboard_shm);
4488N/A return APR_SUCCESS;
4437N/A}
4437N/A
5425N/Astatic void setup_shared_mem(ap_pool_t *p)
5425N/A{
5425N/A char buf[512];
5425N/A const char *fname;
5425N/A
5425N/A fname = ap_server_root_relative(p, ap_scoreboard_fname);
5425N/A if (ap_shm_init(&scoreboard_shm, SCOREBOARD_SIZE + 40, fname, p) != APR_SUCCESS) {
5425N/A ap_snprintf(buf, sizeof(buf), "%s: could not open(create) scoreboard",
5425N/A ap_server_argv0);
5425N/A perror(buf);
5425N/A exit(APEXIT_INIT);
5425N/A }
5425N/A ap_scoreboard_image = ap_shm_malloc(scoreboard_shm, SCOREBOARD_SIZE);
5425N/A if (ap_scoreboard_image == NULL) {
5425N/A ap_snprintf(buf, sizeof(buf), "%s: cannot allocate scoreboard",
5425N/A ap_server_argv0);
5425N/A perror(buf);
5425N/A ap_shm_destroy(scoreboard_shm);
5329N/A exit(APEXIT_INIT);
5329N/A }
5329N/A ap_register_cleanup(p, NULL, cleanup_shared_mem, ap_null_cleanup);
5329N/A}
5349N/A
2236N/Avoid reinit_scoreboard(ap_pool_t *p)
2818N/A{
4910N/A if (ap_scoreboard_image == NULL) {
2N/A setup_shared_mem(p);
5425N/A }
5425N/A memset(ap_scoreboard_image, 0, SCOREBOARD_SIZE);
5425N/A}
5425N/A#endif /* APR_SHARED_MEM */
5425N/A
5425N/A/****
5425N/A * Above code is shmem code. Below code is interacting with the shmem
26N/A ****/
26N/A
181N/Astatic int maintain_connection_status = 1;
181N/A
4353N/Avoid ap_dexter_set_maintain_connection_status(int flag) {
4353N/A maintain_connection_status = flag;
4353N/A return;
4488N/A}
99N/A
59N/A/* Useful to erase the status of children that might be from previous
12N/A * generations */
30N/Avoid ap_dexter_force_reset_connection_status(long conn_id)
4811N/A{
4811N/A int i;
4811N/A
1256N/A for (i = 0; i < STATUSES_PER_CONNECTION; i++) {
1256N/A ap_scoreboard_image->table[conn_id][i].key[0] = '\0';
1256N/A }
2818N/A}
1256N/A
1256N/Avoid ap_reset_connection_status(long conn_id)
1256N/A{
1256N/A if (maintain_connection_status) {
1256N/A ap_dexter_force_reset_connection_status(conn_id);
1256N/A }
1256N/A}
1256N/A
1256N/A/* Don't mess with the string you get back from this function */
2818N/Aconst char *ap_get_connection_status(long conn_id, const char *key)
1256N/A{
1256N/A int i = 0;
1256N/A status_table_entry *ss;
1256N/A
1256N/A if (!maintain_connection_status) return "";
1256N/A while (i < STATUSES_PER_CONNECTION) {
1256N/A ss = &(ap_scoreboard_image->table[conn_id][i]);
3109N/A if (ss->key[0] == '\0') {
3109N/A break;
3109N/A }
3109N/A if (0 == strcmp(ss->key, key)) {
3109N/A return ss->value;
3109N/A }
3109N/A }
3109N/A
3109N/A return NULL;
3109N/A}
3109N/A
3109N/Aap_array_header_t *ap_get_connections(ap_pool_t *p)
3109N/A{
3109N/A int i;
3109N/A ap_array_header_t *connection_list;
3109N/A long *array_slot;
3109N/A
1256N/A connection_list = ap_make_array(p, 0, sizeof(long));
1256N/A /* We assume that there is a connection iff it has an entry in the status
1256N/A * table. Connections without any status sound problematic to me, so this
3109N/A * is probably for the best. - manoj */
4811N/A for (i = 0; i < ap_max_daemons_limit*HARD_THREAD_LIMIT; i++) {
1256N/A if (ap_scoreboard_image->table[i][0].key[0] != '\0') {
26N/A array_slot = ap_push_array(connection_list);
26N/A *array_slot = i;
1256N/A }
2N/A }
26N/A return connection_list;
1256N/A}
1256N/A
185N/Aap_array_header_t *ap_get_connection_keys(ap_pool_t *p, long conn_id)
2N/A{
255N/A int i = 0;
145N/A status_table_entry *ss;
7N/A ap_array_header_t *key_list;
26N/A char **array_slot;
26N/A
38N/A key_list = ap_make_array(p, 0, KEY_LENGTH * sizeof(char));
26N/A while (i < STATUSES_PER_CONNECTION) {
197N/A ss = &(ap_scoreboard_image->table[conn_id][i]);
197N/A if (ss->key[0] == '\0') {
197N/A break;
197N/A }
197N/A array_slot = ap_push_array(key_list);
26N/A *array_slot = ap_pstrdup(p, ss->key);
30N/A i++;
26N/A }
46N/A return key_list;
46N/A}
46N/A
64N/A/* Note: no effort is made here to prevent multiple threads from messing with
64N/A * a single connection at the same time. ap_update_connection_status should
26N/A * only be called by the thread that owns the connection */
46N/A
46N/Avoid ap_update_connection_status(long conn_id, const char *key,
46N/A const char *value)
2N/A{
1256N/A int i = 0;
1256N/A status_table_entry *ss;
1256N/A
1256N/A if (!maintain_connection_status) return;
1256N/A while (i < STATUSES_PER_CONNECTION) {
2818N/A ss = &(ap_scoreboard_image->table[conn_id][i]);
1256N/A if (ss->key[0] == '\0') {
1256N/A break;
1256N/A }
1256N/A if (0 == strcmp(ss->key, key)) {
1256N/A ap_cpystrn(ss->value, value, VALUE_LENGTH);
2818N/A return;
2818N/A }
1256N/A i++;
2236N/A }
2236N/A /* Not found. Add an entry for this value */
1256N/A if (i >= STATUSES_PER_CONNECTION) {
2818N/A /* No room. Oh well, not much anyone can do about it. */
3739N/A return;
5425N/A }
5425N/A ap_cpystrn(ss->key, key, KEY_LENGTH);
5659N/A ap_cpystrn(ss->value, value, VALUE_LENGTH);
5425N/A return;
1256N/A}
1256N/A
1256N/Aap_array_header_t *ap_get_status_table(ap_pool_t *p)
1256N/A{
1256N/A int i, j;
1256N/A ap_array_header_t *server_status;
1256N/A ap_status_table_row_t *array_slot;
3817N/A status_table_entry *ss;
1256N/A
1256N/A server_status = ap_make_array(p, 0, sizeof(ap_status_table_row_t));
1256N/A
1256N/A /* Go ahead and return what's in the connection status table even if we
1256N/A * aren't maintaining it. We can at least look at what children from
2818N/A * previous generations are up to. */
3449N/A
3449N/A for (i = 0; i < ap_max_daemons_limit*HARD_THREAD_LIMIT; i++) {
3449N/A if (ap_scoreboard_image->table[i][0].key[0] == '\0')
3449N/A continue;
3449N/A array_slot = ap_push_array(server_status);
3449N/A array_slot->data = ap_make_table(p, 0);
3449N/A array_slot->conn_id = i;
1934N/A
3739N/A for (j = 0; j < STATUSES_PER_CONNECTION; j++) {
5425N/A ss = &(ap_scoreboard_image->table[i][j]);
5659N/A if (ss->key[0] != '\0') {
5425N/A ap_table_add(array_slot->data, ss->key, ss->value);
1256N/A }
1256N/A else {
1256N/A break;
1413N/A }
1413N/A }
1413N/A }
1413N/A return server_status;
3739N/A}
5425N/A