From: Ryan Bloom Date: Thu, 30 Mar 2000 22:16:37 +0000 (+0000) Subject: An initial implementation for the mpmt_pthread mod_status API. Again, X-Git-Tag: APACHE_2_0_ALPHA_2~14 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b17ff9b58692ad16d732b43ecd2297cd1d98800d;p=thirdparty%2Fapache%2Fhttpd.git 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 --- diff --git a/server/mpm/mpmt_pthread/mpmt_pthread.c b/server/mpm/mpmt_pthread/mpmt_pthread.c index 2bc7326d87c..70bfb2252ac 100644 --- a/server/mpm/mpmt_pthread/mpmt_pthread.c +++ b/server/mpm/mpmt_pthread/mpmt_pthread.c @@ -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. */ 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); @@ -1329,12 +1330,6 @@ int ap_mpm_run(ap_context_t *_pconf, ap_context_t *plog, server_rec *s) "pipe: (pipe_of_death)"); 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) { ap_log_error(APLOG_MARK, APLOG_ERR, errno, diff --git a/server/mpm/mpmt_pthread/scoreboard.c b/server/mpm/mpmt_pthread/scoreboard.c index 31430cb7b96..bf51fe6f5b1 100644 --- a/server/mpm/mpmt_pthread/scoreboard.c +++ b/server/mpm/mpmt_pthread/scoreboard.c @@ -12,6 +12,8 @@ #include 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; /***************************************************************** * @@ -40,14 +42,15 @@ void setup_shared_mem(ap_context_t *p) const char *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_server_argv0); perror(buf); exit(APEXIT_INIT); } 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_server_argv0); 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); } -/* Stub functions until this MPM supports the connection status API */ +/* 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; -API_EXPORT(void) ap_update_connection_status(long conn_id, const char *key, \ - const char *value) + 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) { - /* NOP */ + 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; +} + + diff --git a/server/mpm/mpmt_pthread/scoreboard.h b/server/mpm/mpmt_pthread/scoreboard.h index d23300f7640..bf4edc7a0ae 100644 --- a/server/mpm/mpmt_pthread/scoreboard.h +++ b/server/mpm/mpmt_pthread/scoreboard.h @@ -193,7 +193,22 @@ typedef struct { 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*HARD_THREAD_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 @@ -203,6 +218,8 @@ API_EXPORT(int) ap_exists_scoreboard_image(void); void reinit_scoareboard(ap_context_t *p); void cleanup_scoreboard(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) caddr_t create_shared_heap(const char *name, size_t size);