mirror of
https://github.com/apache/httpd.git
synced 2025-08-20 16:09:55 +00:00
An initial implementation for the mpmt_pthread mod_status API. Again,
this is a working implementation, but it is almost definately not a complete implementation. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@84869 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
@ -1266,6 +1266,7 @@ static void server_main_loop(int remaining_children_to_start)
|
|||||||
/* non-fatal death... note that it's gone in the scoreboard. */
|
/* non-fatal death... note that it's gone in the scoreboard. */
|
||||||
child_slot = find_child_by_pid(pid);
|
child_slot = find_child_by_pid(pid);
|
||||||
if (child_slot >= 0) {
|
if (child_slot >= 0) {
|
||||||
|
ap_mpmt_pthread_force_reset_connection_status(child_slot);
|
||||||
for (i = 0; i < ap_threads_per_child; i++)
|
for (i = 0; i < ap_threads_per_child; i++)
|
||||||
ap_update_child_status(child_slot, i, SERVER_DEAD, (request_rec *) NULL);
|
ap_update_child_status(child_slot, i, SERVER_DEAD, (request_rec *) NULL);
|
||||||
|
|
||||||
@ -1329,12 +1330,6 @@ int ap_mpm_run(ap_context_t *_pconf, ap_context_t *plog, server_rec *s)
|
|||||||
"pipe: (pipe_of_death)");
|
"pipe: (pipe_of_death)");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
/* XXXXXX Removed because these functions don't exist anymore. When
|
|
||||||
These pipes are changed to apr_types, these functions won't be needed
|
|
||||||
anyway.
|
|
||||||
ap_note_cleanups_for_fd(pconf, pipe_of_death[0]);
|
|
||||||
ap_note_cleanups_for_fd(pconf, pipe_of_death[1]);
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (fcntl(pipe_of_death[0], F_SETFD, O_NONBLOCK) == -1) {
|
if (fcntl(pipe_of_death[0], F_SETFD, O_NONBLOCK) == -1) {
|
||||||
ap_log_error(APLOG_MARK, APLOG_ERR, errno,
|
ap_log_error(APLOG_MARK, APLOG_ERR, errno,
|
||||||
|
@ -12,6 +12,8 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
scoreboard *ap_scoreboard_image = NULL;
|
scoreboard *ap_scoreboard_image = NULL;
|
||||||
|
new_scoreboard *ap_new_scoreboard_image = NULL;
|
||||||
|
static int maintain_connection_status = 1;
|
||||||
API_VAR_IMPORT char *ap_scoreboard_fname;
|
API_VAR_IMPORT char *ap_scoreboard_fname;
|
||||||
/*****************************************************************
|
/*****************************************************************
|
||||||
*
|
*
|
||||||
@ -40,14 +42,15 @@ void setup_shared_mem(ap_context_t *p)
|
|||||||
const char *fname;
|
const char *fname;
|
||||||
|
|
||||||
fname = ap_server_root_relative(p, ap_scoreboard_fname);
|
fname = ap_server_root_relative(p, ap_scoreboard_fname);
|
||||||
if (ap_shm_init(&scoreboard_shm, SCOREBOARD_SIZE + 40, fname, p) != APR_SUCCESS) {
|
if (ap_shm_init(&scoreboard_shm, SCOREBOARD_SIZE + NEW_SCOREBOARD_SIZE + 40, fname, p) != APR_SUCCESS) {
|
||||||
ap_snprintf(buf, sizeof(buf), "%s: could not open(create) scoreboard",
|
ap_snprintf(buf, sizeof(buf), "%s: could not open(create) scoreboard",
|
||||||
ap_server_argv0);
|
ap_server_argv0);
|
||||||
perror(buf);
|
perror(buf);
|
||||||
exit(APEXIT_INIT);
|
exit(APEXIT_INIT);
|
||||||
}
|
}
|
||||||
ap_scoreboard_image = ap_shm_malloc(scoreboard_shm, SCOREBOARD_SIZE);
|
ap_scoreboard_image = ap_shm_malloc(scoreboard_shm, SCOREBOARD_SIZE);
|
||||||
if (ap_scoreboard_image == NULL) {
|
ap_new_scoreboard_image = ap_shm_malloc(scoreboard_shm, NEW_SCOREBOARD_SIZE);
|
||||||
|
if (ap_scoreboard_image == NULL || ap_new_scoreboard_image == NULL) {
|
||||||
ap_snprintf(buf, sizeof(buf), "%s: cannot allocate scoreboard",
|
ap_snprintf(buf, sizeof(buf), "%s: cannot allocate scoreboard",
|
||||||
ap_server_argv0);
|
ap_server_argv0);
|
||||||
perror(buf);
|
perror(buf);
|
||||||
@ -236,16 +239,142 @@ void ap_time_process_request(int child_num, int thread_num, int status)
|
|||||||
put_scoreboard_info(child_num, thread_num, ss);
|
put_scoreboard_info(child_num, thread_num, ss);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Stub functions until this MPM supports the connection status API */
|
/* Useful to erase the status of children that might be from previous
|
||||||
|
* generations */
|
||||||
API_EXPORT(void) ap_update_connection_status(long conn_id, const char *key, \
|
void ap_mpmt_pthread_force_reset_connection_status(long conn_id)
|
||||||
const char *value)
|
|
||||||
{
|
{
|
||||||
/* NOP */
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
API_EXPORT(void) ap_reset_connection_status(long 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)
|
||||||
{
|
{
|
||||||
/* NOP */
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ap_array_header_t *ap_get_connections(ap_context_t *p)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
ap_array_header_t *connection_list;
|
||||||
|
long *array_slot;
|
||||||
|
int max_daemons_limit = ap_get_max_daemons();
|
||||||
|
|
||||||
|
connection_list = ap_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 = ap_push_array(connection_list);
|
||||||
|
*array_slot = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return connection_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
ap_array_header_t *ap_get_connection_keys(ap_context_t *p, long conn_id)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
status_table_entry *ss;
|
||||||
|
ap_array_header_t *key_list;
|
||||||
|
char **array_slot;
|
||||||
|
|
||||||
|
key_list = ap_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 = ap_push_array(key_list);
|
||||||
|
*array_slot = ap_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)) {
|
||||||
|
ap_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;
|
||||||
|
}
|
||||||
|
ap_cpystrn(ss->key, key, KEY_LENGTH);
|
||||||
|
ap_cpystrn(ss->value, value, VALUE_LENGTH);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ap_array_header_t *ap_get_status_table(ap_context_t *p)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
ap_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 = ap_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 = ap_push_array(server_status);
|
||||||
|
array_slot->data = ap_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') {
|
||||||
|
ap_table_add(array_slot->data, ss->key, ss->value);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return server_status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -193,7 +193,22 @@ typedef struct {
|
|||||||
global_score global;
|
global_score global;
|
||||||
} scoreboard;
|
} 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*HARD_THREAD_LIMIT][STATUSES_PER_CONNECTION];
|
||||||
|
} new_scoreboard;
|
||||||
|
|
||||||
#define SCOREBOARD_SIZE sizeof(scoreboard)
|
#define SCOREBOARD_SIZE sizeof(scoreboard)
|
||||||
|
#define NEW_SCOREBOARD_SIZE sizeof(new_scoreboard)
|
||||||
#ifdef TPF
|
#ifdef TPF
|
||||||
#define SCOREBOARD_NAME "SCOREBRD"
|
#define SCOREBOARD_NAME "SCOREBRD"
|
||||||
#define SCOREBOARD_FRAMES SCOREBOARD_SIZE/4095 + 1
|
#define SCOREBOARD_FRAMES SCOREBOARD_SIZE/4095 + 1
|
||||||
@ -203,6 +218,8 @@ API_EXPORT(int) ap_exists_scoreboard_image(void);
|
|||||||
void reinit_scoareboard(ap_context_t *p);
|
void reinit_scoareboard(ap_context_t *p);
|
||||||
void cleanup_scoreboard(void);
|
void cleanup_scoreboard(void);
|
||||||
API_EXPORT(void) ap_sync_scoreboard_image(void);
|
API_EXPORT(void) ap_sync_scoreboard_image(void);
|
||||||
|
void ap_mpmt_pthread_force_reset_connection_status(long conn_id);
|
||||||
|
|
||||||
|
|
||||||
#if defined(USE_OS2_SCOREBOARD)
|
#if defined(USE_OS2_SCOREBOARD)
|
||||||
caddr_t create_shared_heap(const char *name, size_t size);
|
caddr_t create_shared_heap(const char *name, size_t size);
|
||||||
|
Reference in New Issue
Block a user