Loading server/mpm/prefork/prefork.c +135 −10 Changes for server/mpm/prefork/prefork.c: 135 added lines, 10 removed lines. Original line number Diff line number Diff line Loading @@ -81,7 +81,6 @@ /* 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: - use ralf's mm stuff for the shared mem and mutexes * TODO: - clean up scoreboard stuff when we figure out how to do it in 2.0 */ Loading Loading @@ -127,6 +126,7 @@ 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 Loading Loading @@ -184,6 +184,7 @@ char tpf_server_name[INETD_SERVNAME_LENGTH+1]; #endif /* TPF */ static scoreboard *ap_scoreboard_image = NULL; static new_scoreboard *ap_new_scoreboard_image = NULL; #ifdef GPROF /* Loading Loading @@ -922,13 +923,14 @@ static 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); ap_new_scoreboard_image = ap_shm_malloc(scoreboard_shm, NEW_SCOREBOARD_SIZE); if (ap_scoreboard_image == NULL) { ap_snprintf(buf, sizeof(buf), "%s: cannot allocate scoreboard", ap_server_argv0); Loading Loading @@ -2156,6 +2158,22 @@ static int setup_listeners(server_rec *s) 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. Loading Loading @@ -2236,6 +2254,7 @@ int ap_mpm_run(ap_context_t *_pconf, ap_context_t *plog, server_rec *s) 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, (request_rec *) NULL); if (remaining_children_to_start Loading Loading @@ -2551,22 +2570,128 @@ static const char *set_coredumpdir (cmd_parms *cmd, void *dummy, char *arg) } /* 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; API_EXPORT(void) ap_update_connection_status(long conn_id, const char *key, \ const char *value) 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) { /* NOP */ int i; ap_array_header_t *connection_list; long *array_slot; 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; 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_status_table(ap_context_t *p) ap_array_header_t *ap_get_connection_keys(ap_context_t *p, long conn_id) { /* NOP */ return NULL; 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; } API_EXPORT(void) ap_reset_connection_status(long conn_id) /* 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) { /* NOP */ int i, j; ap_array_header_t *server_status; ap_status_table_row_t *array_slot; 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; 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; } static const command_rec prefork_cmds[] = { Loading server/mpm/prefork/scoreboard.h +14 −0 Changes for server/mpm/prefork/scoreboard.h: 14 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -190,7 +190,21 @@ 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][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 Loading Loading
server/mpm/prefork/prefork.c +135 −10 Changes for server/mpm/prefork/prefork.c: 135 added lines, 10 removed lines. Original line number Diff line number Diff line Loading @@ -81,7 +81,6 @@ /* 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: - use ralf's mm stuff for the shared mem and mutexes * TODO: - clean up scoreboard stuff when we figure out how to do it in 2.0 */ Loading Loading @@ -127,6 +126,7 @@ 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 Loading Loading @@ -184,6 +184,7 @@ char tpf_server_name[INETD_SERVNAME_LENGTH+1]; #endif /* TPF */ static scoreboard *ap_scoreboard_image = NULL; static new_scoreboard *ap_new_scoreboard_image = NULL; #ifdef GPROF /* Loading Loading @@ -922,13 +923,14 @@ static 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); ap_new_scoreboard_image = ap_shm_malloc(scoreboard_shm, NEW_SCOREBOARD_SIZE); if (ap_scoreboard_image == NULL) { ap_snprintf(buf, sizeof(buf), "%s: cannot allocate scoreboard", ap_server_argv0); Loading Loading @@ -2156,6 +2158,22 @@ static int setup_listeners(server_rec *s) 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. Loading Loading @@ -2236,6 +2254,7 @@ int ap_mpm_run(ap_context_t *_pconf, ap_context_t *plog, server_rec *s) 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, (request_rec *) NULL); if (remaining_children_to_start Loading Loading @@ -2551,22 +2570,128 @@ static const char *set_coredumpdir (cmd_parms *cmd, void *dummy, char *arg) } /* 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; API_EXPORT(void) ap_update_connection_status(long conn_id, const char *key, \ const char *value) 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) { /* NOP */ int i; ap_array_header_t *connection_list; long *array_slot; 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; 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_status_table(ap_context_t *p) ap_array_header_t *ap_get_connection_keys(ap_context_t *p, long conn_id) { /* NOP */ return NULL; 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; } API_EXPORT(void) ap_reset_connection_status(long conn_id) /* 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) { /* NOP */ int i, j; ap_array_header_t *server_status; ap_status_table_row_t *array_slot; 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; 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; } static const command_rec prefork_cmds[] = { Loading
server/mpm/prefork/scoreboard.h +14 −0 Changes for server/mpm/prefork/scoreboard.h: 14 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -190,7 +190,21 @@ 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][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 Loading