]> granicus.if.org Git - php/commitdiff
- add "listen queue len" stat (thx to Andrei Nigmatulin)
authorJérôme Loyet <fat@php.net>
Thu, 11 Nov 2010 02:34:47 +0000 (02:34 +0000)
committerJérôme Loyet <fat@php.net>
Thu, 11 Nov 2010 02:34:47 +0000 (02:34 +0000)
sapi/fpm/config.m4
sapi/fpm/fpm/fpm_conf.c
sapi/fpm/fpm/fpm_config.h
sapi/fpm/fpm/fpm_process_ctl.c
sapi/fpm/fpm/fpm_sockets.c
sapi/fpm/fpm/fpm_sockets.h
sapi/fpm/fpm/fpm_status.c
sapi/fpm/fpm/fpm_status.h
sapi/fpm/fpm/fpm_worker_pool.h

index 6a2105d1e612deb3b68cdc089df6d84e9f178a09..fc5de678045e1962d53821ba0e33ade905e5a405 100644 (file)
@@ -516,6 +516,39 @@ AC_DEFUN([AC_FPM_BUILTIN_ATOMIC],
     AC_MSG_RESULT([no])
   ])
 ])
+
+AC_DEFUN([AC_FPM_LQ],
+[
+  have_lq=no
+
+  AC_MSG_CHECKING([for TCP_INFO])
+
+  AC_TRY_COMPILE([ #include <netinet/tcp.h> ], [struct tcp_info ti; int x = TCP_INFO;], [
+    have_lq=tcp_info
+    AC_MSG_RESULT([yes])
+  ], [
+    AC_MSG_RESULT([no])
+  ])
+
+  if test "$have_lq" = "tcp_info"; then
+    AC_DEFINE([HAVE_LQ_TCP_INFO], 1, [do we have TCP_INFO?])
+  fi
+
+  if test "$have_lq" = "no" ; then
+    AC_MSG_CHECKING([for SO_LISTENQLEN])
+
+    AC_TRY_COMPILE([ #include <sys/socket.h> ], [int x = SO_LISTENQLIMIT; int y = SO_LISTENQLEN;], [
+      have_lq=so_listenq
+      AC_MSG_RESULT([yes])
+    ], [
+      AC_MSG_RESULT([no])
+    ])
+
+    if test "$have_lq" = "tcp_info"; then
+      AC_DEFINE([HAVE_LQ_SO_LISTENQ], 1, [do we have SO_LISTENQxxx?])
+    fi
+  fi
+])
 dnl }}}
 
 AC_MSG_CHECKING(for FPM build)
@@ -543,6 +576,7 @@ if test "$PHP_FPM" != "no"; then
   AC_FPM_CLOCK
   AC_FPM_TRACE
   AC_FPM_BUILTIN_ATOMIC
+  AC_FPM_LQ
 
   PHP_ARG_WITH(fpm-user,,
   [  --with-fpm-user[=USER]  Set the user for php-fpm to run as. (default: nobody)], nobody, no)
index 0b6dda4190b532eb76af59bfbfc80a76a0996dc6..e24d82fe189332af3438a8e5b5c3c44582ab7b60 100644 (file)
@@ -576,7 +576,7 @@ static int fpm_conf_process_all_pools() /* {{{ */
                                return -1;
                        }
                        fpm_status_update_accepted_conn(wp->shm_status, 0);
-                       fpm_status_update_activity(wp->shm_status, -1, -1, -1, 1);
+                       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)); */
index 165bd7d62d18d889bd0aea7c4588af864d8cbaa5..50fb6e52caeea29b77491963b662ba8825b86287 100644 (file)
@@ -42,3 +42,9 @@
 #define HAVE_FPM_TRACE 0
 #endif
 
+#if defined(HAVE_LQ_TCP_INFO) || defined(HAVE_LQ_SO_LISTENQ)
+#define HAVE_FPM_LQ 1
+#else
+#define HAVE_FPM_LQ 0
+#endif
+
index 4eae0a2926fa51cca96c85efa726f591e774a6dd..2a4011ee803b3f349a60c4b2ae2bf9566e3678e0 100644 (file)
@@ -19,6 +19,7 @@
 #include "fpm_request.h"
 #include "fpm_worker_pool.h"
 #include "fpm_status.h"
+#include "fpm_sockets.h"
 #include "zlog.h"
 
 
@@ -327,6 +328,7 @@ static void fpm_pctl_perform_idle_server_maintenance(struct timeval *now, struct
                int idle = 0;
                int active = 0;
                int children_to_fork;
+               unsigned cur_lq;
 
                if (wp->config == NULL) continue;
 
@@ -352,7 +354,10 @@ static void fpm_pctl_perform_idle_server_maintenance(struct timeval *now, struct
                }
 
                /* update status structure for all PMs */
-               fpm_status_update_activity(wp->shm_status, idle, active, idle + active, 0);
+               if (0 > fpm_socket_get_listening_queue(wp, &cur_lq, NULL)) {
+                       cur_lq = 0;
+               }
+               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;
index 31f4c66a62a1f586a3e3f90d7d805c8be8931c5d..80980bbdfb157f259e19fea3c9d83f2a80ae78bc 100644 (file)
@@ -344,6 +344,10 @@ 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;
                }
@@ -373,3 +377,76 @@ int fpm_sockets_init_main() /* {{{ */
 }
 /* }}} */
 
+#if HAVE_FPM_LQ
+
+#ifdef HAVE_LQ_TCP_INFO
+
+#include <netinet/tcp.h>
+
+int fpm_socket_get_listening_queue(struct fpm_worker_pool_s *wp, 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)) {
+               return -1;
+       }
+
+       /* kernel >= 2.6.24 return non-zero here, that means operation is supported */
+       if (info.tcpi_sacked == 0) {
+               return -1;
+       }
+
+       if (cur_lq) {
+               *cur_lq = info.tcpi_unacked;
+       }
+
+       if (max_lq) {
+               *max_lq = info.tcpi_sacked;
+       }
+
+       return 0;
+}
+
+#endif
+
+#ifdef HAVE_LQ_SO_LISTENQ
+
+int fpm_socket_get_listening_queue(struct fpm_worker_pool_s *wp, 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)) {
+                       return -1;
+               }
+
+               *cur_lq = val;
+       }
+
+       if (max_lq) {
+               if (0 > getsockopt(wp->listening_socket, SOL_SOCKET, SO_LISTENQLIMIT, &val, &len)) {
+                       return -1;
+               }
+
+               *max_lq = val;
+       }
+
+       return 0;
+}
+
+#endif
+
+#else
+
+int fpm_socket_get_listening_queue(struct fpm_worker_pool_s *wp, unsigned *cur_lq, unsigned *max_lq)
+{
+       return -1;
+}
+
+#endif
index 8bd778ea5078f871b8c89491582874a0e14bedf9..b74fc234c2b02239f08363857b6c46da513fb386 100644 (file)
@@ -21,6 +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);
 
 
 static inline int fd_set_blocked(int fd, int blocked) /* {{{ */
index 19285b193da6ca7cb854e6fb0f3b2f7174f9ff20..8353375194ec889c6ccea3d9cb7381a41638d320 100644 (file)
@@ -133,7 +133,7 @@ void fpm_status_update_max_children_reached(struct fpm_shm_s *shm, unsigned int
 }
 /* }}} */
 
-void fpm_status_update_activity(struct fpm_shm_s *shm, int idle, int active, int total, int clear_last_update) /* {{{ */
+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;
 
@@ -146,6 +146,8 @@ void fpm_status_update_activity(struct fpm_shm_s *shm, int idle, int active, int
        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 {
@@ -164,14 +166,28 @@ static void fpm_status_handle_status_txt(struct fpm_status_s *status, char **out
        }
 
        spprintf(output, 0, 
-               "accepted conn:        %lu\n"
                "pool:                 %s\n"
                "process manager:      %s\n"
+               "accepted conn:        %lu\n"
+#if HAVE_FPM_LQ
+               "listen queue len:     %u\n"
+               "max listen queue len: %d\n"
+#endif
                "idle processes:       %d\n"
                "active processes:     %d\n"
                "total processes:      %d\n"
                "max children reached: %u\n",
-               status->accepted_conn, fpm_status_pool, status->pm == PM_STYLE_STATIC ? "static" : "dynamic", status->idle, status->active, status->total, status->max_children_reached);
+               fpm_status_pool,
+               status->pm == PM_STYLE_STATIC ? "static" : "dynamic",
+               status->accepted_conn,
+#if HAVE_FPM_LQ
+               status->cur_lq,
+               status->max_lq,
+#endif
+               status->idle,
+               status->active,
+               status->total,
+               status->max_children_reached);
 
        spprintf(content_type, 0, "Content-Type: text/plain");
 }
@@ -185,15 +201,29 @@ static void fpm_status_handle_status_html(struct fpm_status_s *status, char **ou
 
        spprintf(output, 0, 
                "<table>\n"
-               "<tr><th>accepted conn</th><td>%lu</td></tr>\n"
                "<tr><th>pool</th><td>%s</td></tr>\n"
                "<tr><th>process manager</th><td>%s</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"
+#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 children reached</th><td>%u</td></tr>\n"
                "</table>",
-               status->accepted_conn, fpm_status_pool, status->pm == PM_STYLE_STATIC ? "static" : "dynamic", status->idle, status->active, status->total, status->max_children_reached);
+               fpm_status_pool,
+               status->pm == PM_STYLE_STATIC ? "static" : "dynamic",
+               status->accepted_conn,
+#if HAVE_FPM_LQ
+               status->cur_lq,
+               status->max_lq,
+#endif
+               status->idle,
+               status->active,
+               status->total,
+               status->max_children_reached);
 
        spprintf(content_type, 0, "Content-Type: text/html");
 }
@@ -207,15 +237,29 @@ static void fpm_status_handle_status_json(struct fpm_status_s *status, char **ou
 
        spprintf(output, 0, 
                "{"
-               "\"accepted conn\":%lu,"
                "\"pool\":\"%s\","
                "\"process manager\":\"%s\","
+               "\"accepted conn\":%lu,"
+#if HAVE_FPM_LQ
+               "\"listen queue len\":%u,"
+               "\"max listen queue len\":%d,"
+#endif
                "\"idle processes\":%d,"
                "\"active processes\":%d,"
                "\"total processes\":%d,"
                "\"max children reached\":%u"
                "}",
-               status->accepted_conn, fpm_status_pool, status->pm == PM_STYLE_STATIC ? "static" : "dynamic", status->idle, status->active, status->total, status->max_children_reached);
+               fpm_status_pool,
+               status->pm == PM_STYLE_STATIC ? "static" : "dynamic",
+               status->accepted_conn,
+#if HAVE_FPM_LQ
+               status->cur_lq,
+               status->max_lq,
+#endif
+               status->idle,
+               status->active,
+               status->total,
+               status->max_children_reached);
 
        spprintf(content_type, 0, "Content-Type: application/json");
 }
index e081f5eeb0350cb7d251cb468dc708a97f98a655..00e5af54e713f927fd602780b39b28551f7558bf 100644 (file)
@@ -14,13 +14,15 @@ struct fpm_status_s {
        int idle;
        int active;
        int total;
+       unsigned cur_lq;
+       int max_lq;
        unsigned long int accepted_conn;
        unsigned int max_children_reached;
        struct timeval last_update;
 };
 
 int fpm_status_init_child(struct fpm_worker_pool_s *wp);
-void fpm_status_update_activity(struct fpm_shm_s *shm, int idle, int active, int total, int clear_last_update);
+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);
 void fpm_status_update_accepted_conn(struct fpm_shm_s *shm, unsigned long int accepted_conn);
 void fpm_status_increment_accepted_conn(struct fpm_shm_s *shm);
 void fpm_status_set_pm(struct fpm_shm_s *shm, int pm);
index 63aff9a55aa5e25efda401a4e27220372325ce10..7f240a20c28464102265c2436ac0a5f9e89d3813 100644 (file)
@@ -25,6 +25,7 @@ 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;