scoreboard.c revision 666d616b7986a83bb0eac453694fbf4d6f05b98c
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd/* Copyright 2001-2004 The Apache Software Foundation
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd *
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * Licensed under the Apache License, Version 2.0 (the "License");
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * you may not use this file except in compliance with the License.
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * You may obtain a copy of the License at
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd *
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * http://www.apache.org/licenses/LICENSE-2.0
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd *
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * Unless required by applicable law or agreed to in writing, software
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * distributed under the License is distributed on an "AS IS" BASIS,
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen * See the License for the specific language governing permissions and
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen * limitations under the License.
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen */
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd#include "apr.h"
d229f940abfb2490dee17979e9a5ff31b7012eb5rbowen#include "apr_strings.h"
3f08db06526d6901aa08c110b5bc7dde6bc39905nd#include "apr_portable.h"
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd#include "apr_lib.h"
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd#define APR_WANT_STRFUNC
3f08db06526d6901aa08c110b5bc7dde6bc39905nd#include "apr_want.h"
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd
9472e4d3c410be3b3f1addbf3b1db1769f64e765nd#if APR_HAVE_SYS_TYPES_H
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd#include <sys/types.h>
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd#endif
7f5b59ccc63c0c0e3e678a168f09ee6a2f51f9d0nd
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd#include "ap_config.h"
fac8c35bfb158112226ab43ddf84d59daca5dc30nd#include "httpd.h"
f086b4b402fa9a2fefc7dda85de2a3cc1cd0a654rjung#include "http_log.h"
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd#include "http_main.h"
4b575a6b6704b516f22d65a3ad35696d7b9ba372rpluem#include "http_core.h"
4b575a6b6704b516f22d65a3ad35696d7b9ba372rpluem#include "http_config.h"
4b575a6b6704b516f22d65a3ad35696d7b9ba372rpluem#include "ap_mpm.h"
4b575a6b6704b516f22d65a3ad35696d7b9ba372rpluem
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd#include "mpm.h"
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd#include "scoreboard.h"
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34ndAP_DECLARE_DATA scoreboard *ap_scoreboard_image = NULL;
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34ndAP_DECLARE_DATA const char *ap_scoreboard_fname = NULL;
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34ndAP_DECLARE_DATA int ap_extended_status = 0;
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd#if APR_HAS_SHARED_MEMORY
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd#include "apr_shm.h"
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd#ifndef WIN32
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34ndstatic /* but must be exported to mpm_winnt */
30471a4650391f57975f60bbb6e4a90be7b284bfhumbedooh#endif
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd apr_shm_t *ap_scoreboard_shm = NULL;
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd#endif
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34ndAPR_HOOK_STRUCT(
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd APR_HOOK_LINK(pre_mpm)
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd)
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34ndAP_IMPLEMENT_HOOK_RUN_ALL(int,pre_mpm,
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd (apr_pool_t *p, ap_scoreboard_e sb_type),
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd (p, sb_type),OK,DECLINED)
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34ndstatic APR_OPTIONAL_FN_TYPE(ap_proxy_lb_workers)
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd *proxy_lb_workers;
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34ndstruct ap_sb_handle_t {
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd int child_num;
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd int thread_num;
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd};
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34ndstatic int server_limit, thread_limit, lb_limit;
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34ndstatic apr_size_t scoreboard_size;
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd/*
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * ToDo:
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * This function should be renamed to cleanup_shared
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * and it should handle cleaning up a scoreboard shared
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * between processes using any form of IPC (file, shared memory
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * segment, etc.). Leave it as is now because it is being used
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * by various MPMs.
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd */
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34ndstatic apr_status_t ap_cleanup_shared_mem(void *d)
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd{
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd#if APR_HAS_SHARED_MEMORY
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd free(ap_scoreboard_image);
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd ap_scoreboard_image = NULL;
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd apr_shm_destroy(ap_scoreboard_shm);
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd#endif
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd return APR_SUCCESS;
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd}
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34ndAP_DECLARE(apr_size_t) ap_calc_scoreboard_size(void)
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd{
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd ap_mpm_query(AP_MPMQ_HARD_LIMIT_THREADS, &thread_limit);
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd ap_mpm_query(AP_MPMQ_HARD_LIMIT_DAEMONS, &server_limit);
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd if (!proxy_lb_workers)
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd proxy_lb_workers = APR_RETRIEVE_OPTIONAL_FN(ap_proxy_lb_workers);
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd if (proxy_lb_workers)
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd lb_limit = proxy_lb_workers();
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd else
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd lb_limit = 0;
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd scoreboard_size = sizeof(global_score);
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd scoreboard_size += sizeof(process_score) * server_limit;
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd scoreboard_size += sizeof(worker_score) * server_limit * thread_limit;
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd if (lb_limit)
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd scoreboard_size += sizeof(lb_score) * lb_limit;
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd return scoreboard_size;
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd}
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34ndvoid ap_init_scoreboard(void *shared_score)
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd{
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd char *more_storage;
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd int i;
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd ap_calc_scoreboard_size();
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd ap_scoreboard_image =
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd calloc(1, sizeof(scoreboard) + server_limit * sizeof(worker_score *) +
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd server_limit * lb_limit * sizeof(lb_score *));
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd more_storage = shared_score;
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd ap_scoreboard_image->global = (global_score *)more_storage;
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd more_storage += sizeof(global_score);
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd ap_scoreboard_image->parent = (process_score *)more_storage;
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd more_storage += sizeof(process_score) * server_limit;
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd ap_scoreboard_image->servers =
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd (worker_score **)((char*)ap_scoreboard_image + sizeof(scoreboard));
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd for (i = 0; i < server_limit; i++) {
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd ap_scoreboard_image->servers[i] = (worker_score *)more_storage;
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd more_storage += thread_limit * sizeof(worker_score);
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd }
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd if (lb_limit) {
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd ap_scoreboard_image->balancers = (lb_score *)more_storage;
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd more_storage += lb_limit * sizeof(lb_score);
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd }
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd ap_assert(more_storage == (char*)shared_score + scoreboard_size);
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd ap_scoreboard_image->global->server_limit = server_limit;
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd ap_scoreboard_image->global->thread_limit = thread_limit;
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd ap_scoreboard_image->global->lb_limit = lb_limit;
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd}
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd/**
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * Create a name-based scoreboard in the given pool using the
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * given filename.
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd */
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34ndstatic apr_status_t create_namebased_scoreboard(apr_pool_t *pool,
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd const char *fname)
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd{
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd#if APR_HAS_SHARED_MEMORY
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd apr_status_t rv;
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd /* The shared memory file must not exist before we create the
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * segment. */
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd apr_shm_remove(fname, pool); /* ignore errors */
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd rv = apr_shm_create(&ap_scoreboard_shm, scoreboard_size, fname, pool);
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd if (rv != APR_SUCCESS) {
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL,
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd "unable to create scoreboard \"%s\" "
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd "(name-based shared memory failure)", fname);
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd return rv;
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd }
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd#endif /* APR_HAS_SHARED_MEMORY */
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd return APR_SUCCESS;
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd}
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd/* ToDo: This function should be made to handle setting up
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * a scoreboard shared between processes using any IPC technique,
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * not just a shared memory segment
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd */
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34ndstatic apr_status_t open_scoreboard(apr_pool_t *pconf)
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd{
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd#if APR_HAS_SHARED_MEMORY
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd apr_status_t rv;
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd char *fname = NULL;
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd apr_pool_t *global_pool;
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd /* We don't want to have to recreate the scoreboard after
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * restarts, so we'll create a global pool and never clean it.
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd */
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd rv = apr_pool_create(&global_pool, NULL);
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd if (rv != APR_SUCCESS) {
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL,
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd "Fatal error: unable to create global pool "
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd "for use with by the scoreboard");
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd return rv;
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd }
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd /* The config says to create a name-based shmem */
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd if (ap_scoreboard_fname) {
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd /* make sure it's an absolute pathname */
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd fname = ap_server_root_relative(pconf, ap_scoreboard_fname);
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd if (!fname) {
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd ap_log_error(APLOG_MARK, APLOG_CRIT, APR_EBADPATH, NULL,
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd "Fatal error: Invalid Scoreboard path %s",
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd ap_scoreboard_fname);
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd return APR_EBADPATH;
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd }
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd return create_namebased_scoreboard(global_pool, fname);
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd }
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd else { /* config didn't specify, we get to choose shmem type */
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd rv = apr_shm_create(&ap_scoreboard_shm, scoreboard_size, NULL,
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd global_pool); /* anonymous shared memory */
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd if ((rv != APR_SUCCESS) && (rv != APR_ENOTIMPL)) {
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL,
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd "Unable to create scoreboard "
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd "(anonymous shared memory failure)");
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd return rv;
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd }
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd /* Make up a filename and do name-based shmem */
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd else if (rv == APR_ENOTIMPL) {
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd /* Make sure it's an absolute pathname */
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd ap_scoreboard_fname = DEFAULT_SCOREBOARD;
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd fname = ap_server_root_relative(pconf, ap_scoreboard_fname);
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd return create_namebased_scoreboard(global_pool, fname);
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd }
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd }
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd#endif /* APR_HAS_SHARED_MEMORY */
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd return APR_SUCCESS;
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd}
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd/* If detach is non-zero, this is a seperate child process,
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * if zero, it is a forked child.
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd */
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34ndapr_status_t ap_reopen_scoreboard(apr_pool_t *p, apr_shm_t **shm, int detached)
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd{
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd#if APR_HAS_SHARED_MEMORY
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd if (!detached) {
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd return APR_SUCCESS;
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd }
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd if (apr_shm_size_get(ap_scoreboard_shm) < scoreboard_size) {
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd ap_log_error(APLOG_MARK, APLOG_CRIT, 0, NULL,
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd "Fatal error: shared scoreboard too small for child!");
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd apr_shm_detach(ap_scoreboard_shm);
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd ap_scoreboard_shm = NULL;
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd return APR_EINVAL;
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd }
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd /* everything will be cleared shortly */
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd if (*shm) {
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd *shm = ap_scoreboard_shm;
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd }
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd#endif
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd return APR_SUCCESS;
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd}
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34ndapr_status_t ap_cleanup_scoreboard(void *d)
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd{
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd if (ap_scoreboard_image == NULL) {
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd return APR_SUCCESS;
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd }
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd if (ap_scoreboard_image->global->sb_type == SB_SHARED) {
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd ap_cleanup_shared_mem(NULL);
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd }
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd else {
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd free(ap_scoreboard_image->global);
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd free(ap_scoreboard_image);
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd ap_scoreboard_image = NULL;
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd }
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd return APR_SUCCESS;
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd}
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd/* Create or reinit an existing scoreboard. The MPM can control whether
9472e4d3c410be3b3f1addbf3b1db1769f64e765nd * the scoreboard is shared across multiple processes or not
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd */
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34ndint ap_create_scoreboard(apr_pool_t *p, ap_scoreboard_e sb_type)
7f5b59ccc63c0c0e3e678a168f09ee6a2f51f9d0nd{
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd int running_gen = 0;
fac8c35bfb158112226ab43ddf84d59daca5dc30nd int i;
f086b4b402fa9a2fefc7dda85de2a3cc1cd0a654rjung#if APR_HAS_SHARED_MEMORY
30471a4650391f57975f60bbb6e4a90be7b284bfhumbedooh apr_status_t rv;
ba543b319188dc1887607f6d59feddc00e38eee2humbedooh#endif
0d0ba3a410038e179b695446bb149cce6264e0abnd
30471a4650391f57975f60bbb6e4a90be7b284bfhumbedooh if (ap_scoreboard_image) {
0d0ba3a410038e179b695446bb149cce6264e0abnd running_gen = ap_scoreboard_image->global->running_generation;
0d0ba3a410038e179b695446bb149cce6264e0abnd ap_scoreboard_image->global->restart_time = apr_time_now();
0d0ba3a410038e179b695446bb149cce6264e0abnd memset(ap_scoreboard_image->parent, 0,
0d0ba3a410038e179b695446bb149cce6264e0abnd sizeof(process_score) * server_limit);
0d0ba3a410038e179b695446bb149cce6264e0abnd for (i = 0; i < server_limit; i++) {
0d0ba3a410038e179b695446bb149cce6264e0abnd memset(ap_scoreboard_image->servers[i], 0,
0d0ba3a410038e179b695446bb149cce6264e0abnd sizeof(worker_score) * thread_limit);
0d0ba3a410038e179b695446bb149cce6264e0abnd }
0d0ba3a410038e179b695446bb149cce6264e0abnd /* Clean up the lb workers data */
0d0ba3a410038e179b695446bb149cce6264e0abnd if (lb_limit) {
0d0ba3a410038e179b695446bb149cce6264e0abnd memset(ap_scoreboard_image->balancers, 0,
0d0ba3a410038e179b695446bb149cce6264e0abnd sizeof(lb_score) * lb_limit);
0d0ba3a410038e179b695446bb149cce6264e0abnd }
0d0ba3a410038e179b695446bb149cce6264e0abnd return OK;
30471a4650391f57975f60bbb6e4a90be7b284bfhumbedooh }
5effc8b39fae5cd169d17f342bfc265705840014rbowen
d229f940abfb2490dee17979e9a5ff31b7012eb5rbowen ap_calc_scoreboard_size();
0d0ba3a410038e179b695446bb149cce6264e0abnd#if APR_HAS_SHARED_MEMORY
7fec19672a491661b2fe4b29f685bc7f4efa64d4nd if (sb_type == SB_SHARED) {
7fec19672a491661b2fe4b29f685bc7f4efa64d4nd void *sb_shared;
7fec19672a491661b2fe4b29f685bc7f4efa64d4nd rv = open_scoreboard(p);
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd if (rv || !(sb_shared = apr_shm_baseaddr_get(ap_scoreboard_shm))) {
return HTTP_INTERNAL_SERVER_ERROR;
}
memset(sb_shared, 0, scoreboard_size);
ap_init_scoreboard(sb_shared);
}
else
#endif
{
/* A simple malloc will suffice */
void *sb_mem = calloc(1, scoreboard_size);
if (sb_mem == NULL) {
ap_log_error(APLOG_MARK, APLOG_CRIT, 0, NULL,
"(%d)%s: cannot allocate scoreboard",
errno, strerror(errno));
return HTTP_INTERNAL_SERVER_ERROR;
}
ap_init_scoreboard(sb_mem);
}
ap_scoreboard_image->global->sb_type = sb_type;
ap_scoreboard_image->global->running_generation = running_gen;
ap_scoreboard_image->global->restart_time = apr_time_now();
apr_pool_cleanup_register(p, NULL, ap_cleanup_scoreboard, apr_pool_cleanup_null);
return OK;
}
/* 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.
*/
AP_DECLARE(int) ap_exists_scoreboard_image(void)
{
return (ap_scoreboard_image ? 1 : 0);
}
AP_DECLARE(void) ap_increment_counts(ap_sb_handle_t *sb, request_rec *r)
{
worker_score *ws;
ws = &ap_scoreboard_image->servers[sb->child_num][sb->thread_num];
#ifdef HAVE_TIMES
times(&ws->times);
#endif
ws->access_count++;
ws->my_access_count++;
ws->conn_count++;
ws->bytes_served += r->bytes_sent;
ws->my_bytes_served += r->bytes_sent;
ws->conn_bytes += r->bytes_sent;
}
AP_DECLARE(int) find_child_by_pid(apr_proc_t *pid)
{
int i;
int max_daemons_limit;
ap_mpm_query(AP_MPMQ_MAX_DAEMONS, &max_daemons_limit);
for (i = 0; i < max_daemons_limit; ++i) {
if (ap_scoreboard_image->parent[i].pid == pid->pid) {
return i;
}
}
return -1;
}
AP_DECLARE(void) ap_create_sb_handle(ap_sb_handle_t **new_sbh, apr_pool_t *p,
int child_num, int thread_num)
{
*new_sbh = (ap_sb_handle_t *)apr_palloc(p, sizeof(ap_sb_handle_t));
(*new_sbh)->child_num = child_num;
(*new_sbh)->thread_num = thread_num;
}
AP_DECLARE(int) ap_update_child_status_from_indexes(int child_num,
int thread_num,
int status,
request_rec *r)
{
int old_status;
worker_score *ws;
process_score *ps;
if (child_num < 0) {
return -1;
}
ws = &ap_scoreboard_image->servers[child_num][thread_num];
old_status = ws->status;
ws->status = status;
ps = &ap_scoreboard_image->parent[child_num];
if (status == SERVER_READY
&& old_status == SERVER_STARTING) {
ws->thread_num = child_num * thread_limit + thread_num;
ps->generation = ap_my_generation;
}
if (ap_extended_status) {
ws->last_used = apr_time_now();
if (status == SERVER_READY || status == SERVER_DEAD) {
/*
* Reset individual counters
*/
if (status == SERVER_DEAD) {
ws->my_access_count = 0L;
ws->my_bytes_served = 0L;
}
ws->conn_count = 0;
ws->conn_bytes = 0;
}
if (r) {
conn_rec *c = r->connection;
apr_cpystrn(ws->client, ap_get_remote_host(c, r->per_dir_config,
REMOTE_NOLOOKUP, NULL), sizeof(ws->client));
if (r->the_request == NULL) {
apr_cpystrn(ws->request, "NULL", sizeof(ws->request));
} else if (r->parsed_uri.password == NULL) {
apr_cpystrn(ws->request, r->the_request, sizeof(ws->request));
} else {
/* Don't reveal the password in the server-status view */
apr_cpystrn(ws->request, apr_pstrcat(r->pool, r->method, " ",
apr_uri_unparse(r->pool, &r->parsed_uri,
APR_URI_UNP_OMITPASSWORD),
r->assbackwards ? NULL : " ", r->protocol, NULL),
sizeof(ws->request));
}
apr_cpystrn(ws->vhost, r->server->server_hostname,
sizeof(ws->vhost));
}
}
return old_status;
}
AP_DECLARE(int) ap_update_child_status(ap_sb_handle_t *sbh, int status,
request_rec *r)
{
return ap_update_child_status_from_indexes(sbh->child_num, sbh->thread_num,
status, r);
}
void ap_time_process_request(int child_num, int thread_num, int status)
{
worker_score *ws;
if (child_num < 0) {
return;
}
ws = &ap_scoreboard_image->servers[child_num][thread_num];
if (status == START_PREQUEST) {
ws->start_time = apr_time_now();
}
else if (status == STOP_PREQUEST) {
ws->stop_time = apr_time_now();
}
}
AP_DECLARE(worker_score *) ap_get_scoreboard_worker(int x, int y)
{
if (((x < 0) || (server_limit < x)) ||
((y < 0) || (thread_limit < y))) {
return(NULL); /* Out of range */
}
return &ap_scoreboard_image->servers[x][y];
}
AP_DECLARE(process_score *) ap_get_scoreboard_process(int x)
{
if ((x < 0) || (server_limit < x)) {
return(NULL); /* Out of range */
}
return &ap_scoreboard_image->parent[x];
}
AP_DECLARE(global_score *) ap_get_scoreboard_global()
{
return ap_scoreboard_image->global;
}
AP_DECLARE(lb_score *) ap_get_scoreboard_lb(int lb_num)
{
if (((lb_num < 0) || (lb_limit < lb_num))) {
return(NULL); /* Out of range */
}
return &ap_scoreboard_image->balancers[lb_num];
}