]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
An initial implementation for the mpmt_pthread mod_status API. Again,
authorRyan Bloom <rbb@apache.org>
Thu, 30 Mar 2000 22:16:37 +0000 (22:16 +0000)
committerRyan Bloom <rbb@apache.org>
Thu, 30 Mar 2000 22:16:37 +0000 (22:16 +0000)
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

server/mpm/mpmt_pthread/mpmt_pthread.c
server/mpm/mpmt_pthread/scoreboard.c
server/mpm/mpmt_pthread/scoreboard.h

index 2bc7326d87c49289ae384cc596c9922cd1b65628..70bfb2252ac325c99d0deb3a2d06ba3c59a18aad 100644 (file)
@@ -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,
index 31430cb7b966f2c89c92c8ef06582bec192710cf..bf51fe6f5b12fd76ff62d240d8648737142cdf40 100644 (file)
@@ -12,6 +12,8 @@
 #include <sys/types.h>
 
 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;
+}
+
+
index d23300f7640d4fd05f00c7f945b468ac815b94e6..bf4edc7a0ae855cc0408bb96110c4d4dd36d8a28 100644 (file)
@@ -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);