]> granicus.if.org Git - php/commitdiff
- Replaced shm_slots with a real scoreboard
authorJérôme Loyet <fat@php.net>
Sun, 26 Jun 2011 15:48:11 +0000 (15:48 +0000)
committerJérôme Loyet <fat@php.net>
Sun, 26 Jun 2011 15:48:11 +0000 (15:48 +0000)
- Added several improvements to the status page

21 files changed:
sapi/fpm/config.m4
sapi/fpm/fpm/fpm.c
sapi/fpm/fpm/fpm_atomic.h
sapi/fpm/fpm/fpm_children.c
sapi/fpm/fpm/fpm_children.h
sapi/fpm/fpm/fpm_conf.c
sapi/fpm/fpm/fpm_log.c
sapi/fpm/fpm/fpm_main.c
sapi/fpm/fpm/fpm_process_ctl.c
sapi/fpm/fpm/fpm_request.c
sapi/fpm/fpm/fpm_scoreboard.c [new file with mode: 0644]
sapi/fpm/fpm/fpm_scoreboard.h [new file with mode: 0644]
sapi/fpm/fpm/fpm_shm.c
sapi/fpm/fpm/fpm_shm.h
sapi/fpm/fpm/fpm_shm_slots.c [deleted file]
sapi/fpm/fpm/fpm_shm_slots.h [deleted file]
sapi/fpm/fpm/fpm_sockets.c
sapi/fpm/fpm/fpm_sockets.h
sapi/fpm/fpm/fpm_status.c
sapi/fpm/fpm/fpm_worker_pool.c
sapi/fpm/fpm/fpm_worker_pool.h

index 751f866bb2955c6efffe72f84deccb22edd3aa0c..6cdfeb7391011267d075e9acea52eaa41bb72ff1 100644 (file)
@@ -438,7 +438,7 @@ if test "$PHP_FPM" != "no"; then
     fpm/fpm_process_ctl.c \
     fpm/fpm_request.c \
     fpm/fpm_shm.c \
-    fpm/fpm_shm_slots.c \
+    fpm/fpm_scoreboard.c \
     fpm/fpm_signals.c \
     fpm/fpm_sockets.c \
     fpm/fpm_status.c \
index f80f943910664395ccd8e836adc6cf4372a61005..b0b3b2b7a4cddf909bb63941f276459dfd4f6873 100644 (file)
@@ -18,6 +18,7 @@
 #include "fpm_process_ctl.h"
 #include "fpm_conf.h"
 #include "fpm_worker_pool.h"
+#include "fpm_scoreboard.h"
 #include "fpm_stdio.h"
 #include "fpm_log.h"
 #include "zlog.h"
@@ -51,6 +52,7 @@ int fpm_init(int argc, char **argv, char *config, char *prefix, int test_conf) /
                0 > fpm_log_init_main()              ||
                0 > fpm_conf_init_main(test_conf)    ||
                0 > fpm_unix_init_main()             ||
+               0 > fpm_scoreboard_init_main()       ||
                0 > fpm_pctl_init_main()             ||
                0 > fpm_env_init_main()              ||
                0 > fpm_signals_init_main()          ||
index 638bafddc889df78641522f75a9256b2d08ae2dd..662dd4726d5223e0002bc47062f69dc4d49ccd4c 100644 (file)
@@ -146,7 +146,7 @@ static inline atomic_uint_t atomic_cmp_set(atomic_t *lock, atomic_uint_t old, at
 static inline int fpm_spinlock(atomic_t *lock, int try_once) /* {{{ */
 {
        if (try_once) {
-               return atomic_cmp_set(lock, 0, 1) ? 0 : -1;
+               return atomic_cmp_set(lock, 0, 1) ? 1 : 0;
        }
 
        for (;;) {
@@ -158,9 +158,11 @@ static inline int fpm_spinlock(atomic_t *lock, int try_once) /* {{{ */
                sched_yield();
        }
 
-       return 0;
+       return 1;
 }
 /* }}} */
 
+#define fpm_unlock(lock) lock = 0
+
 #endif
 
index d8338725e48c91b00dd55449a16641abd3e490ff..05d741cb89b7c02e1ad3c67a83ea7ff8d7e1bfc2 100644 (file)
@@ -25,7 +25,7 @@
 #include "fpm_stdio.h"
 #include "fpm_unix.h"
 #include "fpm_env.h"
-#include "fpm_shm_slots.h"
+#include "fpm_scoreboard.h"
 #include "fpm_status.h"
 #include "fpm_log.h"
 
@@ -51,6 +51,7 @@ static struct fpm_child_s *fpm_child_alloc() /* {{{ */
        }
 
        memset(ret, 0, sizeof(*ret));
+       ret->scoreboard_i = -1;
        return ret;
 }
 /* }}} */
@@ -238,7 +239,7 @@ void fpm_children_bury() /* {{{ */
 
                        fpm_child_unlink(child);
 
-                       fpm_shm_slots_discard_slot(child);
+                       fpm_scoreboard_proc_free(wp->scoreboard, child->scoreboard_i);
 
                        fpm_clock_get(&tv1);
 
@@ -316,7 +317,7 @@ static struct fpm_child_s *fpm_resources_prepare(struct fpm_worker_pool_s *wp) /
                return 0;
        }
 
-       if (0 > fpm_shm_slots_prepare_slot(c)) {
+       if (0 > fpm_scoreboard_proc_alloc(wp->scoreboard, &c->scoreboard_i)) {
                fpm_stdio_discard_pipes(c);
                fpm_child_free(c);
                return 0;
@@ -328,7 +329,7 @@ static struct fpm_child_s *fpm_resources_prepare(struct fpm_worker_pool_s *wp) /
 
 static void fpm_resources_discard(struct fpm_child_s *child) /* {{{ */
 {
-       fpm_shm_slots_discard_slot(child);
+       fpm_scoreboard_proc_free(child->wp->scoreboard, child->scoreboard_i);
        fpm_stdio_discard_pipes(child);
        fpm_child_free(child);
 }
@@ -336,7 +337,14 @@ static void fpm_resources_discard(struct fpm_child_s *child) /* {{{ */
 
 static void fpm_child_resources_use(struct fpm_child_s *child) /* {{{ */
 {
-       fpm_shm_slots_child_use_slot(child);
+       struct fpm_worker_pool_s *wp;
+       for (wp = fpm_worker_all_pools; wp; wp = wp->next) {
+               if (wp == child->wp) {
+                       continue;
+               }
+               fpm_scoreboard_free(wp->scoreboard);
+       }
+       fpm_scoreboard_child_use(child->wp->scoreboard, child->scoreboard_i, child->pid);
        fpm_stdio_child_use_pipes(child);
        fpm_child_free(child);
 }
@@ -344,7 +352,6 @@ static void fpm_child_resources_use(struct fpm_child_s *child) /* {{{ */
 
 static void fpm_parent_resources_use(struct fpm_child_s *child) /* {{{ */
 {
-       fpm_shm_slots_parent_use_slot(child);
        fpm_stdio_parent_use_pipes(child);
        fpm_child_link(child);
 }
index 4010a4f3b82c00193468277ff219a94af340ed16..9c79f234e8f39c2a19ec9a4605f3414cab6dc880 100644 (file)
@@ -30,6 +30,7 @@ struct fpm_child_s {
        struct timeval slow_logged;
        int idle_kill;
        pid_t pid;
+       int scoreboard_i;
 };
 
 #endif
index f82806644fd3cc4971bd6df30228cb5ea8d242cc..07d982393fc5d65f6043a4c20fa9037f4ce28b69 100644 (file)
@@ -656,16 +656,6 @@ static int fpm_conf_process_all_pools() /* {{{ */
                                        return -1;
                                }
                        }
-                       wp->shm_status = fpm_shm_alloc(sizeof(struct fpm_status_s));
-                       if (!wp->shm_status) {
-                               zlog(ZLOG_ERROR, "[pool %s] unable to allocate shared memory for status page '%s'", wp->config->name, status);
-                               return -1;
-                       }
-                       fpm_status_update_accepted_conn(wp->shm_status, 0);
-                       fpm_status_update_activity(wp->shm_status, -1, -1, -1, 0, -1, 1);
-                       fpm_status_update_max_children_reached(wp->shm_status, 0);
-                       fpm_status_set_pm(wp->shm_status, wp->config->pm);
-                       /* memset(&fpm_status.last_update, 0, sizeof(fpm_status.last_update)); */
                }
 
                if (wp->config->access_log && *wp->config->access_log) {
index 243ed867645f45fe0caa3abfb3973575e6f1cabf..ef1c0c3be382c655beff5c4d1c514c1bf07445e0 100644 (file)
@@ -17,7 +17,7 @@
 #include "fpm_clock.h"
 #include "fpm_process_ctl.h"
 #include "fpm_signals.h"
-#include "fpm_shm_slots.h"
+#include "fpm_scoreboard.h"
 #include "fastcgi.h"
 #include "zlog.h"
 
@@ -28,7 +28,6 @@
 #endif
 
 static char *fpm_log_format = NULL;
-static char *fpm_log_pool = NULL;
 static int fpm_log_fd = -1;
 #ifdef HAVE_TIMES
 static float tick;
@@ -99,10 +98,6 @@ int fpm_log_init_child(struct fpm_worker_pool_s *wp)  /* {{{ */
                }
        }
 
-       if (wp->config->name) {
-               fpm_log_pool = strdup(wp->config->name);
-       }
-
        if (fpm_log_fd == -1) {
                fpm_log_fd = wp->log_fd;
        }
@@ -125,8 +120,8 @@ int fpm_log_write(char *log_format TSRMLS_DC) /* {{{ */
        char buffer[FPM_LOG_BUFFER];
        int token, test;
        size_t len, len2;
-//     fcgi_request *request = (fcgi_request*) SG(server_context);
-       struct fpm_shm_slot_s slot, *slot_p;
+       struct fpm_scoreboard_proc_s proc, *proc_p;
+       struct fpm_scoreboard_s *scoreboard;
        struct timeval uptime, now;
        char tmp[129];
        char format[129];
@@ -148,16 +143,22 @@ int fpm_log_write(char *log_format TSRMLS_DC) /* {{{ */
 
        fpm_clock_get(&now);
        now_epoch = time(NULL);
+
        if (!test) {
-               slot_p = fpm_shm_slots_acquire(0, 0);
-               if (!slot_p) {
-                       zlog(ZLOG_WARNING, "Unable to acquire shm slot");
+               scoreboard = fpm_scoreboard_get();
+               if (!scoreboard) {
+                       zlog(ZLOG_WARNING, "unable to get scoreboard");
+                       return -1;
+               }
+               proc_p = fpm_scoreboard_proc_acquire(NULL, -1, 0);
+               if (!proc_p) {
+                       zlog(ZLOG_WARNING, "[pool %s] Unable to acquire shm slot", scoreboard->pool);
                        return -1;
                }
-               slot = *slot_p;
-               fpm_shm_slots_release(slot_p);
+               proc = *proc_p;
+               fpm_scoreboard_proc_release(proc_p);
 
-               timersub(&now, &slot.accepted, &uptime);
+               timersub(&now, &proc.accepted, &uptime);
        }
 
        token = 0;
@@ -198,18 +199,18 @@ int fpm_log_write(char *log_format TSRMLS_DC) /* {{{ */
                                        if (format[0] == '\0' || !strcasecmp(format, "total")) {
                                                if (!test) {
                                                        tms_total = 
-                                                               (slot.cpu_finished.tms_utime + slot.cpu_finished.tms_stime + slot.cpu_finished.tms_cutime + slot.cpu_finished.tms_cstime)
+                                                               (proc.cpu_finished.tms_utime + proc.cpu_finished.tms_stime + proc.cpu_finished.tms_cutime + proc.cpu_finished.tms_cstime)
                                                                - 
-                                                               (slot.cpu_accepted.tms_utime + slot.cpu_accepted.tms_stime + slot.cpu_accepted.tms_cutime + slot.cpu_accepted.tms_cstime)
+                                                               (proc.cpu_accepted.tms_utime + proc.cpu_accepted.tms_stime + proc.cpu_accepted.tms_cutime + proc.cpu_accepted.tms_cstime)
                                                                ;
                                                }
                                        } else if (!strcasecmp(format, "user")) {
                                                if (!test) {
-                                                       tms_total = (slot.cpu_finished.tms_utime + slot.cpu_finished.tms_cutime) - (slot.cpu_accepted.tms_utime + slot.cpu_accepted.tms_cutime);
+                                                       tms_total = (proc.cpu_finished.tms_utime + proc.cpu_finished.tms_cutime) - (proc.cpu_accepted.tms_utime + proc.cpu_accepted.tms_cutime);
                                                }
                                        } else if (!strcasecmp(format, "system")) {
                                                if (!test) {
-                                                       tms_total = (slot.cpu_finished.tms_stime + slot.cpu_finished.tms_cstime) - (slot.cpu_accepted.tms_stime + slot.cpu_accepted.tms_cstime);
+                                                       tms_total = (proc.cpu_finished.tms_stime + proc.cpu_finished.tms_cstime) - (proc.cpu_accepted.tms_stime + proc.cpu_accepted.tms_cstime);
                                                }
                                        } else {
                                                zlog(ZLOG_WARNING, "only 'total', 'user' or 'system' are allowed as a modifier for %%%c ('%s')", *s, format);
@@ -218,7 +219,7 @@ int fpm_log_write(char *log_format TSRMLS_DC) /* {{{ */
 
                                        format[0] = '\0';
                                        if (!test) {
-                                               len2 = snprintf(b, FPM_LOG_BUFFER - len, "%.2f", tms_total / tick / (slot.cpu_duration.tv_sec + slot.cpu_duration.tv_usec / 1000000.) * 100.);
+                                               len2 = snprintf(b, FPM_LOG_BUFFER - len, "%.2f", tms_total / tick / (proc.cpu_duration.tv_sec + proc.cpu_duration.tv_usec / 1000000.) * 100.);
                                        }
                                        break;
 #endif
@@ -264,19 +265,19 @@ int fpm_log_write(char *log_format TSRMLS_DC) /* {{{ */
 
                                case 'f': /* script */
                                        if (!test) {
-                                               len2 = snprintf(b, FPM_LOG_BUFFER - len, "%s",  slot.script_filename && *slot.script_filename ? slot.script_filename : "-");
+                                               len2 = snprintf(b, FPM_LOG_BUFFER - len, "%s",  proc.script_filename && *proc.script_filename ? proc.script_filename : "-");
                                        }
                                        break;
 
                                case 'l': /* content length */
                                        if (!test) {
-                                               len2 = snprintf(b, FPM_LOG_BUFFER - len, "%zu", slot.content_length);
+                                               len2 = snprintf(b, FPM_LOG_BUFFER - len, "%zu", proc.content_length);
                                        }
                                        break;
 
                                case 'm': /* method */
                                        if (!test) {
-                                               len2 = snprintf(b, FPM_LOG_BUFFER - len, "%s", slot.request_method && *slot.request_method ? slot.request_method : "-");
+                                               len2 = snprintf(b, FPM_LOG_BUFFER - len, "%s", proc.request_method && *proc.request_method ? proc.request_method : "-");
                                        }
                                        break;
 
@@ -284,19 +285,19 @@ int fpm_log_write(char *log_format TSRMLS_DC) /* {{{ */
                                        /* seconds */
                                        if (format[0] == '\0' || !strcasecmp(format, "bytes")) {
                                                if (!test) {
-                                                       len2 = snprintf(b, FPM_LOG_BUFFER - len, "%zu", slot.memory);
+                                                       len2 = snprintf(b, FPM_LOG_BUFFER - len, "%zu", proc.memory);
                                                }
 
                                        /* kilobytes */
                                        } else if (!strcasecmp(format, "kilobytes") || !strcasecmp(format, "kilo")) {
                                                if (!test) {
-                                                       len2 = snprintf(b, FPM_LOG_BUFFER - len, "%lu", slot.memory / 1024);
+                                                       len2 = snprintf(b, FPM_LOG_BUFFER - len, "%lu", proc.memory / 1024);
                                                }
 
                                        /* megabytes */
                                        } else if (!strcasecmp(format, "megabytes") || !strcasecmp(format, "mega")) {
                                                if (!test) {
-                                                       len2 = snprintf(b, FPM_LOG_BUFFER - len, "%lu", slot.memory / 1024 / 1024);
+                                                       len2 = snprintf(b, FPM_LOG_BUFFER - len, "%lu", proc.memory / 1024 / 1024);
                                                }
 
                                        } else {
@@ -308,7 +309,7 @@ int fpm_log_write(char *log_format TSRMLS_DC) /* {{{ */
 
                                case 'n': /* pool name */
                                        if (!test) {
-                                               len2 = snprintf(b, FPM_LOG_BUFFER - len, "%s", fpm_log_pool ? fpm_log_pool : "-");
+                                               len2 = snprintf(b, FPM_LOG_BUFFER - len, "%s", scoreboard->pool[0] ? scoreboard->pool : "-");
                                        }
                                        break;
 
@@ -374,19 +375,19 @@ int fpm_log_write(char *log_format TSRMLS_DC) /* {{{ */
 
                                case 'q': /* query_string */
                                        if (!test) {
-                                               len2 = snprintf(b, FPM_LOG_BUFFER - len, "%s", slot.query_string ? slot.query_string : "");
+                                               len2 = snprintf(b, FPM_LOG_BUFFER - len, "%s", proc.query_string ? proc.query_string : "");
                                        }
                                        break;
 
                                case 'Q': /* '?' */
                                        if (!test) {
-                                               len2 = snprintf(b, FPM_LOG_BUFFER - len, "%s", slot.query_string && *slot.query_string  ? "?" : "");
+                                               len2 = snprintf(b, FPM_LOG_BUFFER - len, "%s", proc.query_string && *proc.query_string  ? "?" : "");
                                        }
                                        break;
 
                                case 'r': /* request URI */
                                        if (!test) {
-                                               len2 = snprintf(b, FPM_LOG_BUFFER - len, "%s", slot.request_uri ? slot.request_uri : "-");
+                                               len2 = snprintf(b, FPM_LOG_BUFFER - len, "%s", proc.request_uri ? proc.request_uri : "-");
                                        }
                                        break;
 
@@ -408,7 +409,7 @@ int fpm_log_write(char *log_format TSRMLS_DC) /* {{{ */
                                        if (!test) {
                                                time_t *t;
                                                if (*s == 't') {
-                                                       t = &slot.accepted_epoch;
+                                                       t = &proc.accepted_epoch;
                                                } else {
                                                        t = &now_epoch;
                                                }
@@ -424,7 +425,7 @@ int fpm_log_write(char *log_format TSRMLS_DC) /* {{{ */
 
                                case 'u': /* remote user */
                                        if (!test) {
-                                               len2 = snprintf(b, FPM_LOG_BUFFER - len, "%s", slot.auth_user ? slot.auth_user : "-");
+                                               len2 = snprintf(b, FPM_LOG_BUFFER - len, "%s", proc.auth_user ? proc.auth_user : "-");
                                        }
                                        break;
 
index 37c932e5b48104da908c3c825c91d5703af21c2e..8946135ad111040cdc1016cc9478b14076f1c3e5 100644 (file)
@@ -1565,7 +1565,6 @@ static zend_module_entry cgi_module_entry = {
  */
 int main(int argc, char *argv[])
 {
-       int free_query_string = 0;
        int exit_status = SUCCESS;
        int cgi = 0, c;
        zend_file_handle file_handle;
@@ -1918,11 +1917,6 @@ fastcgi_request_done:
                                exit_status = EG(exit_status);
                        }
 
-                       if (free_query_string && SG(request_info).query_string) {
-                               free(SG(request_info).query_string);
-                               SG(request_info).query_string = NULL;
-                       }
-
                        requests++;
                        if (max_requests && (requests == max_requests)) {
                                fcgi_finish_request(&request, 1);
index bd50c46c297f1bec33b728b70a99038ee944e30e..c297c2d44a69f71f67d3bd0bf9ff4b32010c79ad 100644 (file)
@@ -18,7 +18,7 @@
 #include "fpm_cleanup.h"
 #include "fpm_request.h"
 #include "fpm_worker_pool.h"
-#include "fpm_status.h"
+#include "fpm_scoreboard.h"
 #include "fpm_sockets.h"
 #include "zlog.h"
 
@@ -337,10 +337,24 @@ static void fpm_pctl_perform_idle_server_maintenance(struct timeval *now) /* {{{
                }
 
                /* update status structure for all PMs */
-               if (0 > fpm_socket_get_listening_queue(wp, &cur_lq, NULL)) {
-                       cur_lq = 0;
+               if (wp->listen_address_domain == FPM_AF_INET) {
+                       if (0 > fpm_socket_get_listening_queue(wp->listening_socket, &cur_lq, NULL)) {
+                               cur_lq = 0;
+#if 0
+                       } else {
+                               if (cur_lq > 0) {
+                                       if (!wp->warn_lq) {
+                                               zlog(ZLOG_WARNING, "[pool %s] listening queue is not empty, #%d requests are waiting to be served, consider raising pm.max_children setting (%d)", wp->config->name, cur_lq, wp->config->pm_max_children);
+                                               wp->warn_lq = 1;
+                                       }
+                               } else {
+                                       wp->warn_lq = 0;
+                               }
+#endif
+                       }
+                       fpm_scoreboard_update(-1, -1, cur_lq, -1, -1, -1, FPM_SCOREBOARD_ACTION_SET, wp->scoreboard);
                }
-               fpm_status_update_activity(wp->shm_status, idle, active, idle + active, cur_lq, wp->listening_queue_len, 0);
+
 
                /* the rest is only used by PM_STYLE_DYNAMIC */
                if (wp->config->pm != PM_STYLE_DYNAMIC) continue;
@@ -357,8 +371,8 @@ static void fpm_pctl_perform_idle_server_maintenance(struct timeval *now) /* {{{
                if (idle < wp->config->pm_min_spare_servers) {
                        if (wp->running_children >= wp->config->pm_max_children) {
                                if (!wp->warn_max_children) {
-                                       fpm_status_increment_max_children_reached(wp->shm_status);
-                                       zlog(ZLOG_WARNING, "[pool %s] server reached max_children setting (%d), consider raising it", wp->config->name, wp->config->pm_max_children);
+                                       fpm_scoreboard_update(0, 0, 0, 0, 0, 1, FPM_SCOREBOARD_ACTION_INC, wp->scoreboard);
+                                       zlog(ZLOG_WARNING, "[pool %s] server reached pm.max_children setting (%d), consider raising it", wp->config->name, wp->config->pm_max_children);
                                        wp->warn_max_children = 1;
                                }
                                wp->idle_spawn_rate = 1;
@@ -366,7 +380,7 @@ static void fpm_pctl_perform_idle_server_maintenance(struct timeval *now) /* {{{
                        }
 
                        if (wp->idle_spawn_rate >= 8) {
-                               zlog(ZLOG_WARNING, "[pool %s] seems busy (you may need to increase start_servers, or min/max_spare_servers), spawning %d children, there are %d idle, and %d total children", wp->config->name, wp->idle_spawn_rate, idle, wp->running_children);
+                               zlog(ZLOG_WARNING, "[pool %s] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning %d children, there are %d idle, and %d total children", wp->config->name, wp->idle_spawn_rate, idle, wp->running_children);
                        }
 
                        /* compute the number of idle process to spawn */
@@ -376,8 +390,8 @@ static void fpm_pctl_perform_idle_server_maintenance(struct timeval *now) /* {{{
                        children_to_fork = MIN(children_to_fork, wp->config->pm_max_children - wp->running_children);
                        if (children_to_fork <= 0) {
                                if (!wp->warn_max_children) {
-                                       fpm_status_increment_max_children_reached(wp->shm_status);
-                                       zlog(ZLOG_WARNING, "[pool %s] server reached max_children setting (%d), consider raising it", wp->config->name, wp->config->pm_max_children);
+                                       fpm_scoreboard_update(0, 0, 0, 0, 0, 1, FPM_SCOREBOARD_ACTION_INC, wp->scoreboard);
+                                       zlog(ZLOG_WARNING, "[pool %s] server reached pm.max_children setting (%d), consider raising it", wp->config->name, wp->config->pm_max_children);
                                        wp->warn_max_children = 1;
                                }
                                wp->idle_spawn_rate = 1;
index 492e76275be12ba8aeadd8bb08d978a23a079e7f..37d161a5c3c0e225f923d1177202421c52c9a76d 100644 (file)
@@ -16,7 +16,7 @@
 #include "fpm_php_trace.h"
 #include "fpm_process_ctl.h"
 #include "fpm_children.h"
-#include "fpm_shm_slots.h"
+#include "fpm_scoreboard.h"
 #include "fpm_status.h"
 #include "fpm_request.h"
 #include "fpm_log.h"
 
 void fpm_request_accepting() /* {{{ */
 {
-       struct fpm_shm_slot_s *slot;
-
-       slot = fpm_shm_slots_acquire(0, 0);
-       slot->request_stage = FPM_REQUEST_ACCEPTING;
-       fpm_clock_get(&slot->tv);
-       memset(slot->request_uri, 0, sizeof(slot->request_uri));
-       memset(slot->request_method, 0, sizeof(slot->request_method));
-       slot->content_length = 0;
-       memset(slot->script_filename, 0, sizeof(slot->script_filename));
-       fpm_shm_slots_release(slot);
+       struct fpm_scoreboard_proc_s *proc;
+       struct timeval now;
+
+       fpm_clock_get(&now);
+
+       proc = fpm_scoreboard_proc_acquire(NULL, -1, 0);
+       if (proc == NULL) {
+               zlog(ZLOG_WARNING, "unable to aquire proc scoreboard");
+               return;
+       }
+
+       proc->request_stage = FPM_REQUEST_ACCEPTING;
+       proc->tv = now;
+       proc->request_uri[0] = '\0';
+       proc->request_method[0] = '\0';
+       proc->script_filename[0] = '\0';
+       proc->content_length = 0;
+       fpm_scoreboard_proc_release(proc);
+
+       /* idle++, active-- */
+       fpm_scoreboard_update(1, -1, 0, 0, 0, 0, FPM_SCOREBOARD_ACTION_INC, NULL);
 }
 /* }}} */
 
 void fpm_request_reading_headers() /* {{{ */
 {
-       struct fpm_shm_slot_s *slot;
+       struct fpm_scoreboard_proc_s *proc;
+
+       struct timeval now;
+       clock_t now_epoch;
+#ifdef HAVE_TIMES
+       struct tms cpu;
+#endif
 
-       slot = fpm_shm_slots_acquire(0, 0);
-       slot->request_stage = FPM_REQUEST_READING_HEADERS;
-       fpm_clock_get(&slot->tv);
-       slot->accepted = slot->tv;
-       slot->accepted_epoch = time(NULL);
+       fpm_clock_get(&now);
+       now_epoch = time(NULL);
 #ifdef HAVE_TIMES
-       times(&slot->cpu_accepted);
+       times(&cpu);
 #endif
-       fpm_shm_slots_release(slot);
 
-       fpm_status_increment_accepted_conn(fpm_status_shm);
+       proc = fpm_scoreboard_proc_acquire(NULL, -1, 0);
+       if (proc == NULL) {
+               zlog(ZLOG_WARNING, "unable to aquire proc scoreboard");
+               return;
+       }
+
+       proc->request_stage = FPM_REQUEST_READING_HEADERS;
+       proc->tv = now;
+       proc->accepted = now;
+       proc->accepted_epoch = now_epoch;
+#ifdef HAVE_TIMES
+       proc->cpu_accepted = cpu;
+#endif
+       fpm_scoreboard_proc_release(proc);
+
+       /* idle--, active++, request++ */
+       fpm_scoreboard_update(-1, 1, 0, 0, 1, 0, FPM_SCOREBOARD_ACTION_INC, NULL);
 }
 /* }}} */
 
 void fpm_request_info() /* {{{ */
 {
        TSRMLS_FETCH();
-       struct fpm_shm_slot_s *slot;
+       struct fpm_scoreboard_proc_s *proc;
        char *request_uri = fpm_php_request_uri(TSRMLS_C);
        char *request_method = fpm_php_request_method(TSRMLS_C);
        char *script_filename = fpm_php_script_filename(TSRMLS_C);
        char *query_string = fpm_php_query_string(TSRMLS_C);
        char *auth_user = fpm_php_auth_user(TSRMLS_C);
+       size_t content_length = fpm_php_content_length(TSRMLS_C);
+       struct timeval now;
+
+       fpm_clock_get(&now);
+
+       proc = fpm_scoreboard_proc_acquire(NULL, -1, 0);
+       if (proc == NULL) {
+               zlog(ZLOG_WARNING, "unable to aquire proc scoreboard");
+               return;
+       }
 
-       slot = fpm_shm_slots_acquire(0, 0);
-       slot->request_stage = FPM_REQUEST_INFO;
-       fpm_clock_get(&slot->tv);
+       proc->request_stage = FPM_REQUEST_INFO;
+       proc->tv = now;
 
        if (request_uri) {
-               strlcpy(slot->request_uri, request_uri, sizeof(slot->request_uri));
+               strlcpy(proc->request_uri, request_uri, sizeof(proc->request_uri));
        }
 
        if (request_method) {
-               strlcpy(slot->request_method, request_method, sizeof(slot->request_method));
+               strlcpy(proc->request_method, request_method, sizeof(proc->request_method));
        }
 
        if (query_string) {
-               strlcpy(slot->query_string, query_string, sizeof(slot->query_string));
+               strlcpy(proc->query_string, query_string, sizeof(proc->query_string));
        }
 
        if (auth_user) {
-               strlcpy(slot->auth_user, auth_user, sizeof(slot->auth_user));
+               strlcpy(proc->auth_user, auth_user, sizeof(proc->auth_user));
        }
 
-       slot->content_length = fpm_php_content_length(TSRMLS_C);
+       proc->content_length = content_length;
 
        /* if cgi.fix_pathinfo is set to "1" and script cannot be found (404)
                the sapi_globals.request_info.path_translated is set to NULL */
        if (script_filename) {
-               strlcpy(slot->script_filename, script_filename, sizeof(slot->script_filename));
+               strlcpy(proc->script_filename, script_filename, sizeof(proc->script_filename));
        }
 
-       fpm_shm_slots_release(slot);
+       fpm_scoreboard_proc_release(proc);
 }
 /* }}} */
 
 void fpm_request_executing() /* {{{ */
 {
-       struct fpm_shm_slot_s *slot;
+       struct fpm_scoreboard_proc_s *proc;
+       struct timeval now;
+
+       fpm_clock_get(&now);
+
+       proc = fpm_scoreboard_proc_acquire(NULL, -1, 0);
+       if (proc == NULL) {
+               zlog(ZLOG_WARNING, "unable to aquire proc scoreboard");
+               return;
+       }
 
-       slot = fpm_shm_slots_acquire(0, 0);
-       slot->request_stage = FPM_REQUEST_EXECUTING;
-       fpm_clock_get(&slot->tv);
-       fpm_shm_slots_release(slot);
+       proc->request_stage = FPM_REQUEST_EXECUTING;
+       proc->tv = now;
+       fpm_scoreboard_proc_release(proc);
 }
 /* }}} */
 
 void fpm_request_end(TSRMLS_D) /* {{{ */
 {
-       struct fpm_shm_slot_s *slot;
+       struct fpm_scoreboard_proc_s *proc;
+       struct timeval now;
+#ifdef HAVE_TIMES
+       struct tms cpu;
+#endif
+       size_t memory = zend_memory_peak_usage(1 TSRMLS_CC);
+
+       fpm_clock_get(&now);
+#ifdef HAVE_TIMES
+       times(&cpu);
+#endif
 
-       slot = fpm_shm_slots_acquire(0, 0);
-       slot->request_stage = FPM_REQUEST_FINISHED;
-       fpm_clock_get(&slot->tv);
+       proc = fpm_scoreboard_proc_acquire(NULL, -1, 0);
+       if (proc == NULL) {
+               zlog(ZLOG_WARNING, "unable to aquire proc scoreboard");
+               return;
+       }
+       proc->request_stage = FPM_REQUEST_FINISHED;
+       proc->tv = now;
 #ifdef HAVE_TIMES
-       times(&slot->cpu_finished);
-       timersub(&slot->tv, &slot->accepted, &slot->cpu_duration);
+       proc->cpu_finished = cpu;
+       timersub(&proc->tv, &proc->accepted, &proc->cpu_duration);
 #endif
-       slot->memory = zend_memory_peak_usage(1 TSRMLS_CC);
-       fpm_shm_slots_release(slot);
+       proc->memory = memory;
+       fpm_scoreboard_proc_release(proc);
 }
 /* }}} */
 
 void fpm_request_finished() /* {{{ */
 {
-       struct fpm_shm_slot_s *slot;
-
-       slot = fpm_shm_slots_acquire(0, 0);
-       slot->request_stage = FPM_REQUEST_FINISHED;
-       fpm_clock_get(&slot->tv);
-       memset(&slot->accepted, 0, sizeof(slot->accepted));
-       slot->accepted_epoch = 0;
-       fpm_shm_slots_release(slot);
+       struct fpm_scoreboard_proc_s *proc;
+       struct timeval now;
+
+       fpm_clock_get(&now);
+
+       proc = fpm_scoreboard_proc_acquire(NULL, -1, 0);
+       if (proc == NULL) {
+               zlog(ZLOG_WARNING, "unable to aquire proc scoreboard");
+               return;
+       }
+
+       proc->request_stage = FPM_REQUEST_FINISHED;
+       proc->tv = now;
+       memset(&proc->accepted, 0, sizeof(proc->accepted));
+       proc->accepted_epoch = 0;
+       fpm_scoreboard_proc_release(proc);
 }
 /* }}} */
 
 void fpm_request_check_timed_out(struct fpm_child_s *child, struct timeval *now, int terminate_timeout, int slowlog_timeout) /* {{{ */
 {
-       struct fpm_shm_slot_s *slot;
-       struct fpm_shm_slot_s slot_c;
+       struct fpm_scoreboard_proc_s proc, *proc_p;
 
-       slot = fpm_shm_slot(child);
-       if (!fpm_shm_slots_acquire(slot, 1)) {
+       proc_p = fpm_scoreboard_proc_acquire(0, child->scoreboard_i, 1);
+       if (!proc_p) {
                return;
        }
 
-       slot_c = *slot;
-       fpm_shm_slots_release(slot);
+       proc = *proc_p;
+       fpm_scoreboard_proc_release(proc_p);
 
 #if HAVE_FPM_TRACE
        if (child->slow_logged.tv_sec) {
-               if (child->slow_logged.tv_sec != slot_c.accepted.tv_sec || child->slow_logged.tv_usec != slot_c.accepted.tv_usec) {
+               if (child->slow_logged.tv_sec != proc.accepted.tv_sec || child->slow_logged.tv_usec != proc.accepted.tv_usec) {
                        child->slow_logged.tv_sec = 0;
                        child->slow_logged.tv_usec = 0;
                }
        }
 #endif
 
-       if (slot_c.request_stage > FPM_REQUEST_ACCEPTING && slot_c.request_stage < FPM_REQUEST_END) {
-               char purified_script_filename[sizeof(slot_c.script_filename)];
+       if (proc.request_stage > FPM_REQUEST_ACCEPTING && proc.request_stage < FPM_REQUEST_END) {
+               char purified_script_filename[sizeof(proc.script_filename)];
                struct timeval tv;
 
-               timersub(now, &slot_c.accepted, &tv);
+               timersub(now, &proc.accepted, &tv);
 
 #if HAVE_FPM_TRACE
                if (child->slow_logged.tv_sec == 0 && slowlog_timeout &&
-                               slot_c.request_stage == FPM_REQUEST_EXECUTING && tv.tv_sec >= slowlog_timeout) {
+                               proc.request_stage == FPM_REQUEST_EXECUTING && tv.tv_sec >= slowlog_timeout) {
                        
-                       str_purify_filename(purified_script_filename, slot_c.script_filename, sizeof(slot_c.script_filename));
+                       str_purify_filename(purified_script_filename, proc.script_filename, sizeof(proc.script_filename));
 
-                       child->slow_logged = slot_c.accepted;
+                       child->slow_logged = proc.accepted;
                        child->tracer = fpm_php_trace;
 
                        fpm_trace_signal(child->pid);
 
                        zlog(ZLOG_WARNING, "[pool %s] child %d, script '%s' (request: \"%s %s\") executing too slow (%d.%06d sec), logging",
-                               child->wp->config->name, (int) child->pid, purified_script_filename, slot_c.request_method, slot_c.request_uri,
+                               child->wp->config->name, (int) child->pid, purified_script_filename, proc.request_method, proc.request_uri,
                                (int) tv.tv_sec, (int) tv.tv_usec);
                }
                else
 #endif
                if (terminate_timeout && tv.tv_sec >= terminate_timeout) {
-                       str_purify_filename(purified_script_filename, slot_c.script_filename, sizeof(slot_c.script_filename));
+                       str_purify_filename(purified_script_filename, proc.script_filename, sizeof(proc.script_filename));
                        fpm_pctl_kill(child->pid, FPM_PCTL_TERM);
 
                        zlog(ZLOG_WARNING, "[pool %s] child %d, script '%s' (request: \"%s %s\") execution timed out (%d.%06d sec), terminating",
-                               child->wp->config->name, (int) child->pid, purified_script_filename, slot_c.request_method, slot_c.request_uri,
+                               child->wp->config->name, (int) child->pid, purified_script_filename, proc.request_method, proc.request_uri,
                                (int) tv.tv_sec, (int) tv.tv_usec);
                }
        }
@@ -197,11 +264,14 @@ void fpm_request_check_timed_out(struct fpm_child_s *child, struct timeval *now,
 
 int fpm_request_is_idle(struct fpm_child_s *child) /* {{{ */
 {
-       struct fpm_shm_slot_s slot;
+       struct fpm_scoreboard_proc_s *proc;
 
        /* no need in atomicity here */
-       slot = *fpm_shm_slot(child);
+       proc = fpm_scoreboard_proc_get(child->wp->scoreboard, child->scoreboard_i);
+       if (!proc) {
+               return 0;
+       }
 
-       return slot.request_stage == FPM_REQUEST_ACCEPTING;
+       return proc->request_stage == FPM_REQUEST_ACCEPTING;
 }
 /* }}} */
diff --git a/sapi/fpm/fpm/fpm_scoreboard.c b/sapi/fpm/fpm/fpm_scoreboard.c
new file mode 100644 (file)
index 0000000..a68e13a
--- /dev/null
@@ -0,0 +1,301 @@
+
+       /* $Id: fpm_status.c 312399 2011-06-23 08:03:52Z fat $ */
+       /* (c) 2009 Jerome Loyet */
+
+#include "php.h"
+#include "SAPI.h"
+#include <stdio.h>
+#include <time.h>
+
+#include "fpm_config.h"
+#include "fpm_scoreboard.h"
+#include "fpm_shm.h"
+#include "fpm_sockets.h"
+#include "fpm_worker_pool.h"
+#include "fpm_clock.h"
+#include "zlog.h"
+
+static struct fpm_scoreboard_s *fpm_scoreboard = NULL;
+static int fpm_scoreboard_i = -1;
+
+int fpm_scoreboard_init_main() /* {{{ */
+{
+       struct fpm_worker_pool_s *wp;
+       int i;
+
+       for (wp = fpm_worker_all_pools; wp; wp = wp->next) {
+               if (wp->config->pm_max_children < 1) {
+                       zlog(ZLOG_ERROR, "[pool %s] Unable to create scoreboard SHM because max_client is not set", wp->config->name);
+                       return -1;
+               }
+
+               if (wp->scoreboard) {
+                       zlog(ZLOG_ERROR, "[pool %s] Unable to create scoreboard SHM because it already exists", wp->config->name);
+                       return -1;
+               }
+
+               wp->scoreboard = fpm_shm_alloc(sizeof(struct fpm_scoreboard_s) + (wp->config->pm_max_children - 1) * sizeof(struct fpm_scoreboard_proc_s *));
+               if (!wp->scoreboard) {
+                       return -1;
+               }
+               wp->scoreboard->nprocs = wp->config->pm_max_children;
+               for (i=0; i<wp->scoreboard->nprocs; i++) {
+                       wp->scoreboard->procs[i] = NULL;
+               }
+
+               wp->scoreboard->pm = wp->config->pm;
+               wp->scoreboard->start_epoch = time(NULL);
+               strlcpy(wp->scoreboard->pool, wp->config->name, sizeof(wp->scoreboard->pool));
+       }
+       return 0;       
+}
+/* }}} */
+
+void fpm_scoreboard_update(int idle, int active, int lq, int lq_len, int requests, int max_children_reached, int action, struct fpm_scoreboard_s *scoreboard) /* {{{ */
+{
+       if (!scoreboard) {
+               scoreboard = fpm_scoreboard;
+       }
+       if (!scoreboard) {
+               zlog(ZLOG_WARNING, "Unable to update scoreboard: the SHM has not been found");
+               return;
+       }
+
+
+       fpm_spinlock(&scoreboard->lock, 0);
+       if (action == FPM_SCOREBOARD_ACTION_SET) {
+               if (idle >= 0) {
+                       scoreboard->idle = idle;
+               }
+               if (active >= 0) {
+                       scoreboard->active = active;
+               }
+               if (lq >= 0) {
+                       scoreboard->lq = lq;
+               }
+               if (lq_len >= 0) {
+                       scoreboard->lq_len = lq_len;
+               }
+#ifdef HAVE_FPM_LQ /* prevent unnecessary test */
+               if (scoreboard->lq > scoreboard->lq_max) {
+                       scoreboard->lq_max = scoreboard->lq;
+               }
+#endif
+               if (requests >= 0) {
+                       scoreboard->requests = requests;
+               }
+
+               if (max_children_reached >= 0) {
+                       scoreboard->max_children_reached = max_children_reached;
+               }
+       } else {
+               if (scoreboard->idle + idle > 0) {
+                       scoreboard->idle += idle;
+               } else {
+                       scoreboard->idle = 0;
+               }
+
+               if (scoreboard->active + active > 0) {
+                       scoreboard->active += active;
+               } else {
+                       scoreboard->active = 0;
+               }
+
+               if (scoreboard->requests + requests > 0) {
+                       scoreboard->requests += requests;
+               } else {
+                       scoreboard->requests = 0;
+               }
+
+               if (scoreboard->max_children_reached + max_children_reached > 0) {
+                       scoreboard->max_children_reached += max_children_reached;
+               } else {
+                       scoreboard->max_children_reached = 0;
+               }
+       }
+
+       if (scoreboard->active > scoreboard->active_max) {
+               scoreboard->active_max = scoreboard->active;
+       }
+
+       fpm_unlock(scoreboard->lock);
+}
+/* }}} */
+
+struct fpm_scoreboard_s *fpm_scoreboard_get() /* {{{*/
+{
+       return fpm_scoreboard;
+}
+/* }}} */
+
+struct fpm_scoreboard_proc_s *fpm_scoreboard_proc_get(struct fpm_scoreboard_s *scoreboard, int child_index) /* {{{*/
+{
+       if (!scoreboard) {
+               scoreboard = fpm_scoreboard;
+       }
+
+       if (!scoreboard) {
+               return NULL;
+       }
+
+       if (child_index < 0) {
+               child_index = fpm_scoreboard_i;
+       }
+
+       if (child_index < 0 || child_index >= scoreboard->nprocs) {
+               return NULL;
+       }
+
+       return scoreboard->procs[child_index];
+}
+/* }}} */
+
+struct fpm_scoreboard_s *fpm_scoreboard_acquire(struct fpm_scoreboard_s *scoreboard, int nohang) /* {{{ */
+{
+       struct fpm_scoreboard_s *s;
+
+       s = scoreboard ? scoreboard : fpm_scoreboard;
+       if (!s) {
+               return NULL;
+       }
+
+       if (!fpm_spinlock(&s->lock, nohang)) {
+               return NULL;
+       }
+       return s;
+}
+/* }}} */
+
+void fpm_scoreboard_release(struct fpm_scoreboard_s *scoreboard) {
+       if (!scoreboard) {
+               return;
+       }
+
+       scoreboard->lock = 0;
+}
+
+struct fpm_scoreboard_proc_s *fpm_scoreboard_proc_acquire(struct fpm_scoreboard_s *scoreboard, int child_index, int nohang) /* {{{ */
+{
+       struct fpm_scoreboard_proc_s *proc;
+
+       proc = fpm_scoreboard_proc_get(scoreboard, child_index);
+       if (!proc) {
+               return NULL;
+       }
+
+       if (!fpm_spinlock(&proc->lock, nohang)) {
+               return NULL;
+       }
+
+       return proc;
+}
+/* }}} */
+
+void fpm_scoreboard_proc_release(struct fpm_scoreboard_proc_s *proc) /* {{{ */
+{
+       if (!proc) {
+               return;
+       }
+
+       proc->lock = 0;
+}
+
+void fpm_scoreboard_free(struct fpm_scoreboard_s *scoreboard) /* {{{ */
+{
+       int i;
+
+       if (!scoreboard) {
+               zlog(ZLOG_ERROR, "**scoreboard is NULL");
+               return;
+       }
+
+       for (i=0; i<scoreboard->nprocs; i++) {
+               if (!scoreboard->procs[i]) {
+                       continue;
+               }
+               fpm_shm_free(scoreboard->procs[i], sizeof(struct fpm_scoreboard_proc_s));
+       }
+       fpm_shm_free(scoreboard, sizeof(struct fpm_scoreboard_s));
+}
+/* }}} */
+
+void fpm_scoreboard_child_use(struct fpm_scoreboard_s *scoreboard, int child_index, pid_t pid) /* {{{ */
+{
+       struct fpm_scoreboard_proc_s *proc;
+       fpm_scoreboard = scoreboard;
+       fpm_scoreboard_i = child_index;
+       proc = fpm_scoreboard_proc_get(scoreboard, child_index);
+       if (!proc) {
+               return;
+       }
+       proc->pid = pid;
+}
+/* }}} */
+
+void fpm_scoreboard_proc_free(struct fpm_scoreboard_s *scoreboard, int child_index) /* {{{ */
+{
+       if (!scoreboard) {
+               return;
+       }
+
+       if (child_index < 0 || child_index >= scoreboard->nprocs) {
+               return;
+       }
+
+       if (scoreboard->procs[child_index]) {
+               fpm_shm_free(scoreboard->procs[child_index], sizeof(struct fpm_scoreboard_proc_s));
+               scoreboard->procs[child_index] = NULL;
+       }
+
+       /* set this slot as free to avoid search on next alloc */
+       scoreboard->free_proc = child_index;
+}
+/* }}} */
+
+int fpm_scoreboard_proc_alloc(struct fpm_scoreboard_s *scoreboard, int *child_index) /* {{{ */
+{
+       int i = -1;
+
+       if (!scoreboard || !child_index) {
+               return -1;
+       }
+
+       /* first try the slot which is supposed to be free */
+       if (scoreboard->free_proc >= 0 && scoreboard->free_proc < scoreboard->nprocs) {
+               if (!scoreboard->procs[scoreboard->free_proc]) {
+                       i = scoreboard->free_proc;
+               }
+       }
+
+       if (i < 0) { /* the supposed free slot is not, let's search for a free slot */
+               zlog(ZLOG_DEBUG, "[pool %s] the proc->free_slot was not free. Let's search", scoreboard->pool);
+               for (i=0; i<scoreboard->nprocs; i++) {
+                       if (!scoreboard->procs[i]) { /* found */
+                               break;
+                       }
+               }
+       }
+
+       /* no free slot */
+       if (i < 0 || i >= scoreboard->nprocs) {
+               zlog(ZLOG_ERROR, "[pool %s] no free scoreboard slot", scoreboard->pool);
+               return -1;
+       }
+
+       scoreboard->procs[i] = fpm_shm_alloc(sizeof(struct fpm_scoreboard_proc_s));
+       if (!scoreboard->procs[i]) {
+               return -1;
+       }
+       *child_index = i;
+
+       /* supposed next slot is free */
+       if (i + 1 >= scoreboard->nprocs) {
+               scoreboard->free_proc = 0;
+       } else {
+               scoreboard->free_proc = i + 1;
+       }
+
+       return 0;
+}
+/* }}} */
+
diff --git a/sapi/fpm/fpm/fpm_scoreboard.h b/sapi/fpm/fpm/fpm_scoreboard.h
new file mode 100644 (file)
index 0000000..0086087
--- /dev/null
@@ -0,0 +1,84 @@
+
+       /* $Id: fpm_status.h 312263 2011-06-18 17:46:16Z felipe $ */
+       /* (c) 2009 Jerome Loyet */
+
+#ifndef FPM_SCOREBOARD_H
+#define FPM_SCOREBOARD_H 1
+
+#include <sys/time.h>
+#ifdef HAVE_TIMES
+#include <sys/times.h>
+#endif
+
+#include "fpm_request.h"
+#include "fpm_worker_pool.h"
+#include "fpm_atomic.h"
+
+#define FPM_SCOREBOARD_ACTION_SET 0
+#define FPM_SCOREBOARD_ACTION_INC 1
+
+struct fpm_scoreboard_proc_s {
+       union {
+               atomic_t lock;
+               char dummy[16];
+       };
+       pid_t pid;
+       enum fpm_request_stage_e request_stage;
+       struct timeval accepted;
+       time_t accepted_epoch;
+       struct timeval tv;
+       char request_uri[128];
+       char query_string[512];
+       char request_method[16];
+       size_t content_length; /* used with POST only */
+       char script_filename[256];
+       char auth_user[32];
+#ifdef HAVE_TIMES
+       struct tms cpu_accepted;
+       struct tms cpu_finished;
+       struct timeval cpu_duration;
+#endif
+       size_t memory;
+};
+
+struct fpm_scoreboard_s {
+       union {
+               atomic_t lock;
+               char dummy[16];
+       };
+       char pool[32];
+       int pm;
+       time_t start_epoch;
+       int idle;
+       int active;
+       int active_max;
+       unsigned long int requests;
+       unsigned int max_children_reached;
+       int lq;
+       int lq_max;
+       unsigned int lq_len;
+       unsigned int nprocs;
+       int free_proc;
+       struct fpm_scoreboard_proc_s *procs[];
+};
+
+int fpm_scoreboard_init_main();
+int fpm_scoreboard_init_child(struct fpm_worker_pool_s *wp);
+
+void fpm_scoreboard_update(int idle, int active, int lq, int lq_len, int requests, int max_children_reached, int action, struct fpm_scoreboard_s *scoreboard);
+struct fpm_scoreboard_s *fpm_scoreboard_get();
+struct fpm_scoreboard_proc_s *fpm_scoreboard_proc_get(struct fpm_scoreboard_s *scoreboard, int child_index);
+
+struct fpm_scoreboard_s *fpm_scoreboard_acquire(struct fpm_scoreboard_s *scoreboard, int nohang);
+void fpm_scoreboard_release(struct fpm_scoreboard_s *scoreboard);
+struct fpm_scoreboard_proc_s *fpm_scoreboard_proc_acquire(struct fpm_scoreboard_s *scoreboard, int child_index, int nohang);
+void fpm_scoreboard_proc_release(struct fpm_scoreboard_proc_s *proc);
+
+void fpm_scoreboard_free(struct fpm_scoreboard_s *scoreboard);
+
+void fpm_scoreboard_child_use(struct fpm_scoreboard_s *scoreboard, int child_index, pid_t pid);
+
+void fpm_scoreboard_proc_free(struct fpm_scoreboard_s *scoreboard, int child_index);
+int fpm_scoreboard_proc_alloc(struct fpm_scoreboard_s *scoreboard, int *child_index);
+
+#endif
index 5f4040990c09fb305ee755e0c68aaab756e27d75..8d068d2784ac9cb6c6f184c9f9dcee00bc2a66e8 100644 (file)
@@ -1,12 +1,10 @@
 
        /* $Id: fpm_shm.c,v 1.3 2008/05/24 17:38:47 anight Exp $ */
-       /* (c) 2007,2008 Andrei Nigmatulin */
+       /* (c) 2007,2008 Andrei Nigmatulin, Jerome Loyet */
 
-#include "fpm_config.h"
-
-#include <unistd.h>
 #include <sys/mman.h>
-#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
 
 #include "fpm_shm.h"
 #include "zlog.h"
 #define MAP_ANONYMOUS MAP_ANON
 #endif
 
-struct fpm_shm_s *fpm_shm_alloc(size_t sz) /* {{{ */
+void *fpm_shm_alloc(size_t size) /* {{{ */
 {
-       struct fpm_shm_s *shm;
+       void *mem;
 
-       shm = malloc(sizeof(*shm));
+       mem = mmap(0, size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0);
 
-       if (!shm) {
-               return 0;
+#ifdef MAP_FAILED
+       if (mem == MAP_FAILED) {
+               zlog(ZLOG_SYSERROR, "unable to allocate %zu bytes in shared memory: %s", size, strerror(errno));
+               return NULL;
        }
+#endif
 
-       shm->mem = mmap(0, sz, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0);
-
-       if (!shm->mem) {
-               zlog(ZLOG_SYSERROR, "mmap(MAP_ANONYMOUS | MAP_SHARED) failed");
-               free(shm);
-               return 0;
+       if (!mem) {
+               zlog(ZLOG_SYSERROR, "unable to allocate %zu bytes in shared memory", size);
+               return NULL;
        }
 
-       shm->used = 0;
-       shm->sz = sz;
-       return shm;
+       memset(mem, size, 0);
+       return mem;
 }
 /* }}} */
 
-void fpm_shm_free(struct fpm_shm_s *shm, int do_unmap) /* {{{ */
+int fpm_shm_free(void *mem, size_t size) /* {{{ */
 {
-       if (do_unmap) {
-               munmap(shm->mem, shm->sz);
+       if (!mem) {
+               zlog(ZLOG_ERROR, "mem is NULL");
+               return 0;
        }
-       free(shm);      
-}
-/* }}} */
 
-void fpm_shm_free_list(struct fpm_shm_s *shm, void *mem) /* {{{ */
-{
-       struct fpm_shm_s *next;
-
-       for (; shm; shm = next) {
-               next = shm->next;
-               fpm_shm_free(shm, mem != shm->mem);
+       if (munmap(mem, size) == -1) {
+               zlog(ZLOG_SYSERROR, "Unable to free shm: %s", strerror(errno));
+               return 0;
        }
-}
-/* }}} */
-
-void *fpm_shm_alloc_chunk(struct fpm_shm_s **head, size_t sz, void **mem) /* {{{ */
-{
-       size_t pagesize = getpagesize();
-       static const size_t cache_line_size = 16;
-       size_t aligned_sz;
-       struct fpm_shm_s *shm;
-       void *ret;
-
-       sz = (sz + cache_line_size - 1) & -cache_line_size;
-       shm = *head;
-
-       if (0 == shm || shm->sz - shm->used < sz) {
-               /* allocate one more shm segment */
 
-               aligned_sz = (sz + pagesize - 1) & -pagesize;
-               shm = fpm_shm_alloc(aligned_sz);
-
-               if (!shm) {
-                       return 0;
-               }
-
-               shm->next = *head;
-
-               if (shm->next) {
-                       shm->next->prev = shm;
-               }
-
-               shm->prev = 0;
-               *head = shm;
-       }
 
-       *mem = shm->mem;
-       ret = (char *) shm->mem + shm->used;
-       shm->used += sz;
-       return ret;
+       return 1;
 }
 /* }}} */
 
index bbff54c4021c3db82562a690dd0eb0fe6b671296..bcc3d8c1a86a090020892dd2c5814e34223a8905 100644 (file)
@@ -5,19 +5,8 @@
 #ifndef FPM_SHM_H
 #define FPM_SHM_H 1
 
-struct fpm_shm_s;
-
-struct fpm_shm_s {
-       struct fpm_shm_s *prev, *next;
-       void *mem;
-       size_t sz;
-       size_t used;
-};
-
-struct fpm_shm_s *fpm_shm_alloc(size_t sz);
-void fpm_shm_free(struct fpm_shm_s *shm, int do_unmap);
-void fpm_shm_free_list(struct fpm_shm_s *, void *);
-void *fpm_shm_alloc_chunk(struct fpm_shm_s **head, size_t sz, void **mem);
+void *fpm_shm_alloc(size_t size);
+int fpm_shm_free(void *mem, size_t size);
 
 #endif
 
diff --git a/sapi/fpm/fpm/fpm_shm_slots.c b/sapi/fpm/fpm/fpm_shm_slots.c
deleted file mode 100644 (file)
index 2c10d6b..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-
-       /* $Id: fpm_shm_slots.c,v 1.2 2008/05/24 17:38:47 anight Exp $ */
-       /* (c) 2007,2008 Andrei Nigmatulin */
-
-#include "fpm_config.h"
-
-#include "fpm_atomic.h"
-#include "fpm_worker_pool.h"
-#include "fpm_children.h"
-#include "fpm_shm.h"
-#include "fpm_shm_slots.h"
-#include "zlog.h"
-
-static void *shm_mem;
-static struct fpm_shm_slot_s *shm_slot;
-
-int fpm_shm_slots_prepare_slot(struct fpm_child_s *child) /* {{{ */
-{
-       struct fpm_worker_pool_s *wp = child->wp;
-       struct fpm_shm_slot_ptr_s *shm_slot_ptr;
-
-       child->shm_slot_i = wp->slots_used.used;
-       shm_slot_ptr = fpm_array_push(&wp->slots_used);
-
-       if (0 == shm_slot_ptr) {
-               return -1;
-       }
-
-       if (0 == wp->slots_free.used) {
-               shm_slot_ptr->shm_slot = fpm_shm_alloc_chunk(&wp->shm_list, sizeof(struct fpm_shm_slot_s), &shm_slot_ptr->mem);
-               if (!shm_slot_ptr->shm_slot) {
-                       return -1;
-               }
-       } else {
-               *shm_slot_ptr = *(struct fpm_shm_slot_ptr_s *) fpm_array_item_last(&wp->slots_free);
-               --wp->slots_free.used;
-       }
-
-       memset(shm_slot_ptr->shm_slot, 0, sizeof(struct fpm_shm_slot_s));
-       shm_slot_ptr->child = child;
-       return 0;
-}
-/* }}} */
-
-void fpm_shm_slots_discard_slot(struct fpm_child_s *child) /* {{{ */
-{
-       struct fpm_shm_slot_ptr_s *shm_slot_ptr;
-       struct fpm_worker_pool_s *wp = child->wp;
-       int n;
-
-       shm_slot_ptr = fpm_array_push(&wp->slots_free);
-       if (shm_slot_ptr) {
-               struct fpm_shm_slot_ptr_s *shm_slot_ptr_used;
-
-               shm_slot_ptr_used = fpm_array_item(&wp->slots_used, child->shm_slot_i);
-               *shm_slot_ptr = *shm_slot_ptr_used;
-               shm_slot_ptr->child = 0;
-       }
-
-       n = fpm_array_item_remove(&wp->slots_used, child->shm_slot_i);
-       if (n > -1) {
-               shm_slot_ptr = fpm_array_item(&wp->slots_used, n);
-               shm_slot_ptr->child->shm_slot_i = n;
-       }
-}
-/* }}} */
-
-void fpm_shm_slots_child_use_slot(struct fpm_child_s *child) /* {{{ */
-{
-       struct fpm_shm_slot_ptr_s *shm_slot_ptr;
-       struct fpm_worker_pool_s *wp = child->wp;
-
-       shm_slot_ptr = fpm_array_item(&wp->slots_used, child->shm_slot_i);
-       shm_slot = shm_slot_ptr->shm_slot;
-       shm_mem = shm_slot_ptr->mem;
-}
-/* }}} */
-
-void fpm_shm_slots_parent_use_slot(struct fpm_child_s *child) /* {{{ */
-{
-       /* nothing to do */
-}
-/* }}} */
-
-void *fpm_shm_slots_mem() /* {{{ */
-{
-       return shm_mem;
-}
-/* }}} */
-
-struct fpm_shm_slot_s *fpm_shm_slot(struct fpm_child_s *child) /* {{{ */
-{
-       struct fpm_shm_slot_ptr_s *shm_slot_ptr;
-       struct fpm_worker_pool_s *wp = child->wp;
-
-       shm_slot_ptr = fpm_array_item(&wp->slots_used, child->shm_slot_i);
-       return shm_slot_ptr->shm_slot;
-}
-/* }}} */
-
-struct fpm_shm_slot_s *fpm_shm_slots_acquire(struct fpm_shm_slot_s *s, int nohang) /* {{{ */
-{
-       if (s == 0) {
-               s = shm_slot;
-       }
-
-       if (0 > fpm_spinlock(&s->lock, nohang)) {
-               return 0;
-       }
-       return s;
-}
-/* }}} */
-
-void fpm_shm_slots_release(struct fpm_shm_slot_s *s) /* {{{ */
-{
-       s->lock = 0;
-}
-/* }}} */
-
diff --git a/sapi/fpm/fpm/fpm_shm_slots.h b/sapi/fpm/fpm/fpm_shm_slots.h
deleted file mode 100644 (file)
index 0330384..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-
-       /* $Id: fpm_shm_slots.h,v 1.2 2008/05/24 17:38:47 anight Exp $ */
-       /* (c) 2007,2008 Andrei Nigmatulin */
-
-#ifndef FPM_SHM_SLOTS_H
-#define FPM_SHM_SLOTS_H 1
-
-#ifdef HAVE_TIMES
-#include <sys/times.h>
-#endif
-
-#include "fpm_atomic.h"
-#include "fpm_worker_pool.h"
-#include "fpm_request.h"
-
-struct fpm_child_s;
-
-struct fpm_shm_slot_s {
-       union {
-               atomic_t lock;
-               char dummy[16];
-       };
-       enum fpm_request_stage_e request_stage;
-       struct timeval accepted;
-       time_t accepted_epoch;
-       struct timeval tv;
-       char request_uri[128];
-       char query_string[512];
-       char request_method[16];
-       size_t content_length; /* used with POST only */
-       char script_filename[256];
-       char auth_user[32];
-#ifdef HAVE_TIMES
-       struct tms cpu_accepted;
-       struct tms cpu_finished;
-       struct timeval cpu_duration;
-#endif
-       size_t memory;
-};
-
-struct fpm_shm_slot_ptr_s {
-       void *mem;
-       struct fpm_shm_slot_s *shm_slot;
-       struct fpm_child_s *child;
-};
-
-int fpm_shm_slots_prepare_slot(struct fpm_child_s *child);
-void fpm_shm_slots_discard_slot(struct fpm_child_s *child);
-void fpm_shm_slots_child_use_slot(struct fpm_child_s *child);
-void fpm_shm_slots_parent_use_slot(struct fpm_child_s *child);
-void *fpm_shm_slots_mem();
-struct fpm_shm_slot_s *fpm_shm_slot(struct fpm_child_s *child);
-struct fpm_shm_slot_s *fpm_shm_slots_acquire(struct fpm_shm_slot_s *, int nohang);
-void fpm_shm_slots_release(struct fpm_shm_slot_s *);
-
-#endif
-
index d8931502643d558dce7be3c73d5a9362824db577..08e2342e56cfb20f7a5c0d2144b576e344589314 100644 (file)
@@ -28,6 +28,7 @@
 #include "fpm_str.h"
 #include "fpm_env.h"
 #include "fpm_cleanup.h"
+#include "fpm_scoreboard.h"
 
 struct listening_socket_s {
        int refcount;
@@ -207,6 +208,7 @@ static int fpm_sockets_new_listening_socket(struct fpm_worker_pool_s *wp, struct
                zlog(ZLOG_SYSERROR, "listen() for address '%s' failed", wp->config->listen_address);
                return -1;
        }
+
        return sock;
 }
 /* }}} */
@@ -222,6 +224,7 @@ static int fpm_sockets_get_listening_socket(struct fpm_worker_pool_s *wp, struct
 
        sock = fpm_sockets_new_listening_socket(wp, sa, socklen);
        fpm_sockets_hash_op(sock, sa, 0, wp->listen_address_domain, FPM_STORE_USE_SOCKET);
+
        return sock;
 }
 /* }}} */
@@ -294,7 +297,7 @@ static int fpm_socket_af_unix_listening_socket(struct fpm_worker_pool_s *wp) /*
 
 int fpm_sockets_init_main() /* {{{ */
 {
-       unsigned i;
+       unsigned i, lq_len;
        struct fpm_worker_pool_s *wp;
        char *inherited = getenv("FPM_SOCKETS");
        struct listening_socket_s *ls;
@@ -344,13 +347,13 @@ int fpm_sockets_init_main() /* {{{ */
                                break;
                }
 
-               if (0 > fpm_socket_get_listening_queue(wp, NULL, (unsigned *) &wp->listening_queue_len)) {
-                       wp->listening_queue_len = -1;
-               }
-
                if (wp->listening_socket == -1) {
                        return -1;
                }
+
+       if (wp->listen_address_domain == FPM_AF_INET && fpm_socket_get_listening_queue(wp->listening_socket, NULL, &lq_len) >= 0) {
+                       fpm_scoreboard_update(-1, -1, -1, (int)lq_len, -1, -1, FPM_SCOREBOARD_ACTION_SET, wp->scoreboard);
+               }
        }
 
        /* close unused sockets that was inherited */
@@ -383,16 +386,13 @@ int fpm_sockets_init_main() /* {{{ */
 
 #include <netinet/tcp.h>
 
-int fpm_socket_get_listening_queue(struct fpm_worker_pool_s *wp, unsigned *cur_lq, unsigned *max_lq)
+int fpm_socket_get_listening_queue(int sock, unsigned *cur_lq, unsigned *max_lq)
 {
-       if (wp->listen_address_domain != FPM_AF_INET) {
-               return -1;
-       }
-
        struct tcp_info info;
        socklen_t len = sizeof(info);
 
-       if (0 > getsockopt(wp->listening_socket, IPPROTO_TCP, TCP_INFO, &info, &len)) {
+       if (0 > getsockopt(sock, IPPROTO_TCP, TCP_INFO, &info, &len)) {
+               zlog(ZLOG_SYSERROR, "unable to retrieve TCP_INFO for socket");
                return -1;
        }
 
@@ -416,13 +416,13 @@ int fpm_socket_get_listening_queue(struct fpm_worker_pool_s *wp, unsigned *cur_l
 
 #ifdef HAVE_LQ_SO_LISTENQ
 
-int fpm_socket_get_listening_queue(struct fpm_worker_pool_s *wp, unsigned *cur_lq, unsigned *max_lq)
+int fpm_socket_get_listening_queue(int sock, unsigned *cur_lq, unsigned *max_lq)
 {
        int val;
        socklen_t len = sizeof(val);
 
        if (cur_lq) {
-               if (0 > getsockopt(wp->listening_socket, SOL_SOCKET, SO_LISTENQLEN, &val, &len)) {
+               if (0 > getsockopt(sock, SOL_SOCKET, SO_LISTENQLEN, &val, &len)) {
                        return -1;
                }
 
@@ -430,7 +430,7 @@ int fpm_socket_get_listening_queue(struct fpm_worker_pool_s *wp, unsigned *cur_l
        }
 
        if (max_lq) {
-               if (0 > getsockopt(wp->listening_socket, SOL_SOCKET, SO_LISTENQLIMIT, &val, &len)) {
+               if (0 > getsockopt(sock, SOL_SOCKET, SO_LISTENQLIMIT, &val, &len)) {
                        return -1;
                }
 
@@ -444,7 +444,7 @@ int fpm_socket_get_listening_queue(struct fpm_worker_pool_s *wp, unsigned *cur_l
 
 #else
 
-int fpm_socket_get_listening_queue(struct fpm_worker_pool_s *wp, unsigned *cur_lq, unsigned *max_lq)
+int fpm_socket_get_listening_queue(int sock, unsigned *cur_lq, unsigned *max_lq)
 {
        return -1;
 }
index b74fc234c2b02239f08363857b6c46da513fb386..447fbff4b245b04098a8e37446f49fdedb7ecee9 100644 (file)
@@ -21,7 +21,7 @@
 
 enum fpm_address_domain fpm_sockets_domain_from_address(char *addr);
 int fpm_sockets_init_main();
-int fpm_socket_get_listening_queue(struct fpm_worker_pool_s *wp, unsigned *cur_lq, unsigned *max_lq);
+int fpm_socket_get_listening_queue(int sock, unsigned *cur_lq, unsigned *max_lq);
 
 
 static inline int fd_set_blocked(int fd, int blocked) /* {{{ */
index 63f15d6e971c7236667c1f72fa0b18070d2c452e..9fab7e7fb3dbd870f47b4bd6b0508d528bc44e98 100644 (file)
@@ -7,13 +7,13 @@
 #include <stdio.h>
 
 #include "fpm_config.h"
+#include "fpm_scoreboard.h"
 #include "fpm_status.h"
 #include "fpm_clock.h"
-#include "fpm_shm_slots.h"
+#include "fpm_scoreboard.h"
 #include "zlog.h"
+#include "fpm_atomic.h"
 
-struct fpm_shm_s *fpm_status_shm = NULL;
-static char *fpm_status_pool = NULL;
 static char *fpm_status_uri = NULL;
 static char *fpm_status_ping_uri = NULL;
 static char *fpm_status_ping_response = NULL;
@@ -25,146 +25,30 @@ int fpm_status_init_child(struct fpm_worker_pool_s *wp) /* {{{ */
                zlog(ZLOG_ERROR, "unable to init fpm_status because conf structure is NULL");
                return -1;
        }
-       if (wp->config->pm_status_path || wp->config->ping_path) {
-               if (wp->config->pm_status_path) {
-                       if (!wp->shm_status) {
-                               zlog(ZLOG_ERROR, "[pool %s] unable to init fpm_status because the dedicated SHM has not been set", wp->config->name);
-                               return -1;
-                       }
-                       fpm_status_shm = wp->shm_status;
-               }
-               fpm_status_pool = strdup(wp->config->name);
-               if (wp->config->pm_status_path) {
-                       fpm_status_uri = strdup(wp->config->pm_status_path);
-               }
-               if (wp->config->ping_path) {
-                       if (!wp->config->ping_response) {
-                               zlog(ZLOG_ERROR, "[pool %s] ping is set (%s) but pong is not set.", wp->config->name, wp->config->ping_path);
-                               return -1;
-                       }
-                       fpm_status_ping_uri = strdup(wp->config->ping_path);
-                       fpm_status_ping_response = strdup(wp->config->ping_response);
-               }
-       }
-       return 0;
-}
-/* }}} */
-
-void fpm_status_set_pm(struct fpm_shm_s *shm, int pm) /* {{{ */
-{
-       struct fpm_status_s status;
-
-       if (!shm) shm = fpm_status_shm;
-       if (!shm || !shm->mem) return;
-
-       /* one shot operation */
-       status = *(struct fpm_status_s *)shm->mem;
-
-       status.pm = pm;
-
-       /* one shot operation */
-       *(struct fpm_status_s *)shm->mem = status;
-}
-/* }}} */
 
-void fpm_status_increment_accepted_conn(struct fpm_shm_s *shm) /* {{{ */
-{
-       struct fpm_status_s status;
-
-       if (!shm) shm = fpm_status_shm;
-       if (!shm || !shm->mem) return;
-
-       /* one shot operation */
-       status = *(struct fpm_status_s *)shm->mem;
-
-       status.accepted_conn++;
-
-       /* one shot operation */
-       *(struct fpm_status_s *)shm->mem = status;
-}
-/* }}} */
-
-void fpm_status_update_accepted_conn(struct fpm_shm_s *shm, unsigned long int accepted_conn) /* {{{ */
-{
-       struct fpm_status_s status;
-
-       if (!shm) shm = fpm_status_shm;
-       if (!shm || !shm->mem) return;
-
-       /* one shot operation */
-       status = *(struct fpm_status_s *)shm->mem;
-
-       status.accepted_conn = accepted_conn;
-
-       /* one shot operation */
-       *(struct fpm_status_s *)shm->mem = status;
-}
-/* }}} */
-
-void fpm_status_increment_max_children_reached(struct fpm_shm_s *shm) /* {{{ */
-{
-       struct fpm_status_s status;
-
-       if (!shm) shm = fpm_status_shm;
-       if (!shm || !shm->mem) return;
-
-       /* one shot operation */
-       status = *(struct fpm_status_s *)shm->mem;
-
-       status.max_children_reached++;
-
-       /* one shot operation */
-       *(struct fpm_status_s *)shm->mem = status;
-}
-/* }}} */
-
-void fpm_status_update_max_children_reached(struct fpm_shm_s *shm, unsigned int max_children_reached) /* {{{ */
-{
-       struct fpm_status_s status;
-
-       if (!shm) shm = fpm_status_shm;
-       if (!shm || !shm->mem) return;
-
-       /* one shot operation */
-       status = *(struct fpm_status_s *)shm->mem;
-
-       status.max_children_reached = max_children_reached;
-
-       /* one shot operation */
-       *(struct fpm_status_s *)shm->mem = status;
-}
-/* }}} */
-
-void fpm_status_update_activity(struct fpm_shm_s *shm, int idle, int active, int total, unsigned cur_lq, int max_lq, int clear_last_update) /* {{{ */
-{
-       struct fpm_status_s status;
-
-       if (!shm) shm = fpm_status_shm;
-       if (!shm || !shm->mem) return;
-
-       /* one shot operation */
-       status = *(struct fpm_status_s *)shm->mem;
+       if (wp->config->pm_status_path) {
+               fpm_status_uri = strdup(wp->config->pm_status_path);
+       }
 
-       status.idle = idle;
-       status.active = active;
-       status.total = total;
-       status.cur_lq = cur_lq;
-       status.max_lq = max_lq;
-       if (clear_last_update) {
-               memset(&status.last_update, 0, sizeof(status.last_update));
-       } else {
-               fpm_clock_get(&status.last_update);
+       if (wp->config->ping_path) {
+               if (!wp->config->ping_response) {
+                       zlog(ZLOG_ERROR, "[pool %s] ping is set (%s) but pong is not set.", wp->config->name, wp->config->ping_path);
+                       return -1;
+               }
+               fpm_status_ping_uri = strdup(wp->config->ping_path);
+               fpm_status_ping_response = strdup(wp->config->ping_response);
        }
 
-       /* one shot operation */
-       *(struct fpm_status_s *)shm->mem = status;
+       return 0;
 }
 /* }}} */
 
 int fpm_status_handle_request(TSRMLS_D) /* {{{ */
 {
-       struct fpm_status_s status;
-       char *buffer, *syntax;
+       struct fpm_scoreboard_s scoreboard, *scoreboard_p;
+//     struct fpm_scoreboard_proc_s proc;
+       char *buffer, *syntax, *time_format, time_buffer[64];
+       time_t now_epoch;
 
        if (!SG(request_info).request_uri) {
                return 0;
@@ -181,19 +65,28 @@ int fpm_status_handle_request(TSRMLS_D) /* {{{ */
        /* STATUS */
        if (fpm_status_uri && !strcmp(fpm_status_uri, SG(request_info).request_uri)) {
 
-               if (!fpm_status_shm || !fpm_status_shm->mem) {
-                       zlog(ZLOG_ERROR, "[pool %s] unable to find or access status shared memory", fpm_status_pool);
+               scoreboard_p = fpm_scoreboard_get();
+               if (!scoreboard_p) {
+                       zlog(ZLOG_ERROR, "status: unable to find or access status shared memory");
                        SG(sapi_headers).http_response_code = 500;
                        sapi_add_header_ex(ZEND_STRL("Content-Type: text/plain"), 1, 1 TSRMLS_CC);
                        PUTS("Internal error. Please review log file for errors.");
                        return 1;
                }
 
-               /* one shot operation */
-               status = *(struct fpm_status_s *)fpm_status_shm->mem;
+               if (!fpm_spinlock(&scoreboard_p->lock, 1)) {
+                       zlog(ZLOG_NOTICE, "[pool %s] status: scoreboard already in used.", scoreboard_p->pool);
+                       SG(sapi_headers).http_response_code = 503;
+                       sapi_add_header_ex(ZEND_STRL("Content-Type: text/plain"), 1, 1 TSRMLS_CC);
+                       PUTS("Server busy. Please try again later.");
+                       return 1;
+               }
+               /* copy the scoreboard not to bother other processes */
+               scoreboard = *scoreboard_p;
+               fpm_unlock(scoreboard_p->lock);
 
-               if (status.idle < 0 || status.active < 0 || status.total < 0) {
-                       zlog(ZLOG_ERROR, "[pool %s] invalid status values", fpm_status_pool);
+               if (scoreboard.idle < 0 || scoreboard.active < 0) {
+                       zlog(ZLOG_ERROR, "[pool %s] invalid status values", scoreboard.pool);
                        SG(sapi_headers).http_response_code = 500;
                        sapi_add_header_ex(ZEND_STRL("Content-Type: text/plain"), 1, 1 TSRMLS_CC);
                        PUTS("Internal error. Please review log file for errors.");
@@ -203,88 +96,113 @@ int fpm_status_handle_request(TSRMLS_D) /* {{{ */
                /* HTML */
                if (SG(request_info).query_string && strstr(SG(request_info).query_string, "html")) {
                        sapi_add_header_ex(ZEND_STRL("Content-Type: text/html"), 1, 1 TSRMLS_CC);
+                       time_format = "%d/%b/%Y:%H:%M:%S %z";
                        syntax =
                                "<table>\n"
                                "<tr><th>pool</th><td>%s</td></tr>\n"
                                "<tr><th>process manager</th><td>%s</td></tr>\n"
+                               "<tr><th>start time</th><td>%s</td></tr>\n"
+                               "<tr><th>start since</th><td>%lu</td></tr>\n"
                                "<tr><th>accepted conn</th><td>%lu</td></tr>\n"
 #if HAVE_FPM_LQ
-                               "<tr><th>listen queue len</th><td>%u</td></tr>\n"
-                               "<tr><th>max listen queue len</th><td>%d</td></tr>\n"
+                               "<tr><th>listen queue</th><td>%u</td></tr>\n"
+                               "<tr><th>max listen queue</th><td>%u</td></tr>\n"
+                               "<tr><th>listen queue len</th><td>%d</td></tr>\n"
 #endif
                                "<tr><th>idle processes</th><td>%d</td></tr>\n"
                                "<tr><th>active processes</th><td>%d</td></tr>\n"
                                "<tr><th>total processes</th><td>%d</td></tr>\n"
+                               "<tr><th>max active processes</th><td>%d</td></tr>\n"
                                "<tr><th>max children reached</th><td>%u</td></tr>\n"
                                "</table>";
 
                /* XML */
                } else if (SG(request_info).request_uri && strstr(SG(request_info).query_string, "xml")) {
                        sapi_add_header_ex(ZEND_STRL("Content-Type: text/xml"), 1, 1 TSRMLS_CC);
+                       time_format = "%s";
                        syntax =
                                "<?xml version=\"1.0\" ?>\n"
                                "<status>\n"
                                "<pool>%s</pool>\n"
                                "<process-manager>%s</process-manager>\n"
+                               "<start-time>%s</start-time>\n"
+                               "<start-since>%lu</start-since>\n"
                                "<accepted-conn>%lu</accepted-conn>\n"
 #if HAVE_FPM_LQ
-                               "<listen-queue-len>%u</listen-queue-len>\n"
-                               "<max-listen-queue-len>%d</max-listen-queue-len>\n"
+                               "<listen-queue>%u</listen-queue>\n"
+                               "<max-listen-queue>%u</max-listen-queue>\n"
+                               "<listen-queue-len>%d</listen-queue-len>\n"
 #endif
                                "<idle-processes>%d</idle-processes>\n"
                                "<active-processes>%d</active-processes>\n"
                                "<total-processes>%d</total-processes>\n"
+                               "<max-active-processes>%d</max-active-processes>\n"
                                "<max-children-reached>%u</max-children-reached>\n"
                                "</status>";
 
                        /* JSON */
                } else if (SG(request_info).request_uri && strstr(SG(request_info).query_string, "json")) {
                        sapi_add_header_ex(ZEND_STRL("Content-Type: application/json"), 1, 1 TSRMLS_CC);
-
+                       time_format = "%s";
                        syntax =
                                "{"
                                "\"pool\":\"%s\","
                                "\"process manager\":\"%s\","
+                               "\"start time\":%s,"
+                               "\"start since\":%lu,"
                                "\"accepted conn\":%lu,"
 #if HAVE_FPM_LQ
-                               "\"listen queue len\":%u,"
-                               "\"max listen queue len\":%d,"
+                               "\"listen queue\":%u,"
+                               "\"max listen queue\":%u,"
+                               "\"listen queue len\":%d,"
 #endif
                                "\"idle processes\":%d,"
                                "\"active processes\":%d,"
                                "\"total processes\":%d,"
+                               "\"max active processes\":%d,"
                                "\"max children reached\":%u"
                                "}";
 
                /* TEXT */
                } else {
                        sapi_add_header_ex(ZEND_STRL("Content-Type: text/plain"), 1, 1 TSRMLS_CC);
+                       time_format = "%d/%b/%Y:%H:%M:%S %z";
                        syntax =
                                "pool:                 %s\n"
                                "process manager:      %s\n"
+                               "start time:           %s\n"
+                               "start since:          %lu\n"
                                "accepted conn:        %lu\n"
 #if HAVE_FPM_LQ
-                               "listen queue len:     %u\n"
-                               "max listen queue len: %d\n"
+                               "listen queue:         %u\n"
+                               "max listen queue:     %u\n"
+                               "listen queue len:     %d\n"
 #endif
                                "idle processes:       %d\n"
                                "active processes:     %d\n"
                                "total processes:      %d\n"
+                               "max active processes: %d\n"
                                "max children reached: %u\n";
                }
 
+               strftime(time_buffer, sizeof(time_buffer) - 1, time_format, localtime(&scoreboard.start_epoch));
+               now_epoch = time(NULL);
                spprintf(&buffer, 0, syntax,
-                               fpm_status_pool,
-                               status.pm == PM_STYLE_STATIC ? "static" : "dynamic",
-                               status.accepted_conn,
+                               scoreboard.pool,
+                               scoreboard.pm == PM_STYLE_STATIC ? "static" : "dynamic",
+                               time_buffer,
+                               now_epoch - scoreboard.start_epoch,
+                               scoreboard.requests,
 #if HAVE_FPM_LQ
-                               status.cur_lq,
-                               status.max_lq,
+                               scoreboard.lq,
+                               scoreboard.lq_max,
+                               scoreboard.lq_len,
 #endif
-                               status.idle,
-                               status.active,
-                               status.total,
-                               status.max_children_reached);
+                               scoreboard.idle,
+                               scoreboard.active,
+                               scoreboard.idle + scoreboard.active,
+                               scoreboard.active_max,
+                               scoreboard.max_children_reached);
 
                SG(sapi_headers).http_response_code = 200;
                PUTS(buffer);
index e799e3502637391594783251b1a24517732f7a12..6c6d9cce03be3322bea35a6039e26a3d458dd896 100644 (file)
@@ -13,8 +13,9 @@
 #include "fpm_cleanup.h"
 #include "fpm_children.h"
 #include "fpm_shm.h"
-#include "fpm_shm_slots.h"
+#include "fpm_scoreboard.h"
 #include "fpm_conf.h"
+#include "zlog.h"
 
 struct fpm_worker_pool_s *fpm_worker_all_pools;
 
@@ -26,18 +27,15 @@ static void fpm_worker_pool_cleanup(int which, void *arg) /* {{{ */
                wp_next = wp->next;
                fpm_worker_pool_config_free(wp->config);
                fpm_children_free(wp->children);
-               fpm_array_free(&wp->slots_used);
-               fpm_array_free(&wp->slots_free);
-               fpm_shm_free_list(wp->shm_list, which == FPM_CLEANUP_CHILD ? fpm_shm_slots_mem() : 0);
-               if (wp->shm_status && which != FPM_CLEANUP_CHILD) {
-                       fpm_shm_free(wp->shm_status, !fpm_globals.is_child);
+               if ((which & FPM_CLEANUP_CHILD) == 0 && fpm_globals.parent_pid == getpid()) {
+                       fpm_scoreboard_free(wp->scoreboard);
                }
                free(wp->config);
                free(wp->user);
                free(wp->home);
                free(wp);
        }
-       fpm_worker_all_pools = 0;
+       fpm_worker_all_pools = NULL;
 }
 /* }}} */
 
@@ -52,8 +50,6 @@ struct fpm_worker_pool_s *fpm_worker_pool_alloc() /* {{{ */
 
        memset(ret, 0, sizeof(struct fpm_worker_pool_s));
 
-       fpm_array_init(&ret->slots_used, sizeof(struct fpm_shm_slot_ptr_s), 50);
-       fpm_array_init(&ret->slots_free, sizeof(struct fpm_shm_slot_ptr_s), 50);
        ret->idle_spawn_rate = 1;
        ret->log_fd = -1;
        return ret;
index e014255cf148fcaa60e8c44f6f9102f4cde291e9..098def5b7e2764e2b1bc636359560e70cc95010d 100644 (file)
@@ -6,7 +6,6 @@
 #define FPM_WORKER_POOL_H 1
 
 #include "fpm_conf.h"
-#include "fpm_arrays.h"
 #include "fpm_shm.h"
 
 struct fpm_worker_pool_s;
@@ -25,20 +24,18 @@ struct fpm_worker_pool_s {
        char *user, *home;                                                                      /* for setting env USER and HOME */
        enum fpm_address_domain listen_address_domain;
        int listening_socket;
-       int listening_queue_len;
        int set_uid, set_gid;                                                           /* config uid and gid */
        int socket_uid, socket_gid, socket_mode;
 
-       struct fpm_shm_s *shm_list;
-       struct fpm_array_s slots_used;
-       struct fpm_array_s slots_free;
-
        /* runtime */
        struct fpm_child_s *children;
        int running_children;
        int idle_spawn_rate;
        int warn_max_children;
-       struct fpm_shm_s *shm_status;
+#if 0
+       int warn_lq;
+#endif
+       struct fpm_scoreboard_s *scoreboard;
        int log_fd;
 };