- Replaced shm_slots with a real scoreboard

- Added several improvements to the status page
This commit is contained in:
Jérôme Loyet 2011-06-26 15:48:11 +00:00
parent 27934faf97
commit dace636cc9
21 changed files with 737 additions and 591 deletions

View 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 \

View 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() ||

View 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

View 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);
}

View File

@ -30,6 +30,7 @@ struct fpm_child_s {
struct timeval slow_logged;
int idle_kill;
pid_t pid;
int scoreboard_i;
};
#endif

View 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) {

View 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;
}
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;

View 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);

View 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;

View 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"
@ -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;
}
/* }}} */

View 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;
}
/* }}} */

View 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

View 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"
@ -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;
}
/* }}} */

View 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

View File

@ -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;
}
/* }}} */

View File

@ -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

View 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;
}

View 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) /* {{{ */

View 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);
}
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);

View 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;

View 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;
};