mirror of
https://github.com/php/php-src.git
synced 2024-09-23 19:07:26 +00:00
- Replaced shm_slots with a real scoreboard
- Added several improvements to the status page
This commit is contained in:
parent
27934faf97
commit
dace636cc9
@ -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 \
|
||||
|
@ -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() ||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ struct fpm_child_s {
|
||||
struct timeval slow_logged;
|
||||
int idle_kill;
|
||||
pid_t pid;
|
||||
int scoreboard_i;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
slot = *slot_p;
|
||||
fpm_shm_slots_release(slot_p);
|
||||
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;
|
||||
}
|
||||
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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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"
|
||||
@ -25,170 +25,237 @@
|
||||
|
||||
void fpm_request_accepting() /* {{{ */
|
||||
{
|
||||
struct fpm_shm_slot_s *slot;
|
||||
struct fpm_scoreboard_proc_s *proc;
|
||||
struct timeval now;
|
||||
|
||||
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);
|
||||
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;
|
||||
|
||||
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);
|
||||
struct timeval now;
|
||||
clock_t now_epoch;
|
||||
#ifdef HAVE_TIMES
|
||||
times(&slot->cpu_accepted);
|
||||
struct tms cpu;
|
||||
#endif
|
||||
fpm_shm_slots_release(slot);
|
||||
|
||||
fpm_status_increment_accepted_conn(fpm_status_shm);
|
||||
fpm_clock_get(&now);
|
||||
now_epoch = time(NULL);
|
||||
#ifdef HAVE_TIMES
|
||||
times(&cpu);
|
||||
#endif
|
||||
|
||||
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;
|
||||
|
||||
slot = fpm_shm_slots_acquire(0, 0);
|
||||
slot->request_stage = FPM_REQUEST_INFO;
|
||||
fpm_clock_get(&slot->tv);
|
||||
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_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;
|
||||
|
||||
slot = fpm_shm_slots_acquire(0, 0);
|
||||
slot->request_stage = FPM_REQUEST_EXECUTING;
|
||||
fpm_clock_get(&slot->tv);
|
||||
fpm_shm_slots_release(slot);
|
||||
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_EXECUTING;
|
||||
proc->tv = now;
|
||||
fpm_scoreboard_proc_release(proc);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
void fpm_request_end(TSRMLS_D) /* {{{ */
|
||||
{
|
||||
struct fpm_shm_slot_s *slot;
|
||||
|
||||
slot = fpm_shm_slots_acquire(0, 0);
|
||||
slot->request_stage = FPM_REQUEST_FINISHED;
|
||||
fpm_clock_get(&slot->tv);
|
||||
struct fpm_scoreboard_proc_s *proc;
|
||||
struct timeval now;
|
||||
#ifdef HAVE_TIMES
|
||||
times(&slot->cpu_finished);
|
||||
timersub(&slot->tv, &slot->accepted, &slot->cpu_duration);
|
||||
struct tms cpu;
|
||||
#endif
|
||||
slot->memory = zend_memory_peak_usage(1 TSRMLS_CC);
|
||||
fpm_shm_slots_release(slot);
|
||||
size_t memory = zend_memory_peak_usage(1 TSRMLS_CC);
|
||||
|
||||
fpm_clock_get(&now);
|
||||
#ifdef HAVE_TIMES
|
||||
times(&cpu);
|
||||
#endif
|
||||
|
||||
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
|
||||
proc->cpu_finished = cpu;
|
||||
timersub(&proc->tv, &proc->accepted, &proc->cpu_duration);
|
||||
#endif
|
||||
proc->memory = memory;
|
||||
fpm_scoreboard_proc_release(proc);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
void fpm_request_finished() /* {{{ */
|
||||
{
|
||||
struct fpm_shm_slot_s *slot;
|
||||
struct fpm_scoreboard_proc_s *proc;
|
||||
struct timeval now;
|
||||
|
||||
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);
|
||||
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;
|
||||
}
|
||||
/* }}} */
|
||||
|
301
sapi/fpm/fpm/fpm_scoreboard.c
Normal file
301
sapi/fpm/fpm/fpm_scoreboard.c
Normal file
@ -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;
|
||||
}
|
||||
/* }}} */
|
||||
|
84
sapi/fpm/fpm/fpm_scoreboard.h
Normal file
84
sapi/fpm/fpm/fpm_scoreboard.h
Normal file
@ -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
|
@ -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"
|
||||
@ -17,85 +15,43 @@
|
||||
#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) {
|
||||
#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
|
||||
|
||||
if (!mem) {
|
||||
zlog(ZLOG_SYSERROR, "unable to allocate %zu bytes in shared memory", size);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(mem, size, 0);
|
||||
return mem;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
int fpm_shm_free(void *mem, size_t size) /* {{{ */
|
||||
{
|
||||
if (!mem) {
|
||||
zlog(ZLOG_ERROR, "mem is NULL");
|
||||
return 0;
|
||||
}
|
||||
|
||||
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);
|
||||
if (munmap(mem, size) == -1) {
|
||||
zlog(ZLOG_SYSERROR, "Unable to free shm: %s", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
shm->used = 0;
|
||||
shm->sz = sz;
|
||||
return shm;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
void fpm_shm_free(struct fpm_shm_s *shm, int do_unmap) /* {{{ */
|
||||
{
|
||||
if (do_unmap) {
|
||||
munmap(shm->mem, shm->sz);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
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;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
/* }}} */
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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) /* {{{ */
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/* one shot operation */
|
||||
*(struct fpm_status_s *)shm->mem = status;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user