Browse Source
- Replaced shm_slots with a real scoreboard
- Replaced shm_slots with a real scoreboard
- Added several improvements to the status pagepull/271/head
21 changed files with 729 additions and 583 deletions
-
2sapi/fpm/config.m4
-
2sapi/fpm/fpm/fpm.c
-
6sapi/fpm/fpm/fpm_atomic.h
-
19sapi/fpm/fpm/fpm_children.c
-
1sapi/fpm/fpm/fpm_children.h
-
10sapi/fpm/fpm/fpm_conf.c
-
63sapi/fpm/fpm/fpm_log.c
-
6sapi/fpm/fpm/fpm_main.c
-
32sapi/fpm/fpm/fpm_process_ctl.c
-
212sapi/fpm/fpm/fpm_request.c
-
301sapi/fpm/fpm/fpm_scoreboard.c
-
84sapi/fpm/fpm/fpm_scoreboard.h
-
92sapi/fpm/fpm/fpm_shm.c
-
15sapi/fpm/fpm/fpm_shm.h
-
119sapi/fpm/fpm/fpm_shm_slots.c
-
57sapi/fpm/fpm/fpm_shm_slots.h
-
30sapi/fpm/fpm/fpm_sockets.c
-
2sapi/fpm/fpm/fpm_sockets.h
-
234sapi/fpm/fpm/fpm_status.c
-
14sapi/fpm/fpm/fpm_worker_pool.c
-
11sapi/fpm/fpm/fpm_worker_pool.h
@ -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; |
|||
} |
|||
/* }}} */ |
|||
|
|||
@ -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,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 |
|||
|
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue