php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login | |
Patch fpm-ondemand-pm-php53 for FPM related Bug #52569Patch version 2010-08-10 18:01 UTC Return to Bug #52569 | Download this patchThis patch is obsolete Obsoleted by patches:
This patch renders other patches obsolete Obsolete patches: Patch Revisions:Developer: mplomer@gmx.deIndex: fpm_children.c =================================================================== --- fpm_children.c (revision 302051) +++ fpm_children.c (working copy) @@ -361,6 +361,12 @@ } else { max = wp->running_children + nb_to_spawn; } + } else if (wp->config->pm == PM_STYLE_ONDEMAND) { + if (!in_event_loop) { /* starting */ + max = 0; + } else { + max = wp->running_children + nb_to_spawn; + } } else { /* PM_STYLE_STATIC */ max = wp->config->pm_max_children; } @@ -411,6 +417,20 @@ int fpm_children_create_initial(struct fpm_worker_pool_s *wp, struct event_base *base) /* {{{ */ { + if (wp->config->pm == PM_STYLE_ONDEMAND) { + wp->socket_event = (struct event *)malloc(sizeof(struct event)); + if (!wp->socket_event) { + zlog(ZLOG_STUFF, ZLOG_ERROR, "[pool %s] unable to malloc the socket event", wp->config->name); + return 1; + } + wp->base = base; + wp->last_fork.tv_sec = 0; + wp->last_fork.tv_usec = 0; + event_set(wp->socket_event, wp->listening_socket, EV_PERSIST | EV_READ, fpm_pctl_on_socket_accept, wp); + event_base_set(base, wp->socket_event); + event_add(wp->socket_event, 0); + return 1; + } return fpm_children_make(wp, 0 /* not in event loop yet */, 0, 1, base); } /* }}} */ Index: fpm_conf.c =================================================================== --- fpm_conf.c (revision 302051) +++ fpm_conf.c (working copy) @@ -259,6 +259,8 @@ c->pm = PM_STYLE_STATIC; } else if (!strcasecmp(val, "dynamic")) { c->pm = PM_STYLE_DYNAMIC; + } else if (!strcasecmp(val, "ondemand")) { + c->pm = PM_STYLE_ONDEMAND; } else { return "invalid process manager (static or dynamic)"; } @@ -430,8 +432,8 @@ return -1; } - if (wp->config->pm != PM_STYLE_STATIC && wp->config->pm != PM_STYLE_DYNAMIC) { - zlog(ZLOG_STUFF, ZLOG_ALERT, "[pool %s] the process manager is missing (static or dynamic)", wp->config->name); + if (wp->config->pm != PM_STYLE_STATIC && wp->config->pm != PM_STYLE_DYNAMIC && wp->config->pm != PM_STYLE_ONDEMAND) { + zlog(ZLOG_STUFF, ZLOG_ALERT, "[pool %s] the process manager is missing (static, dynamic or ondemand)", wp->config->name); return -1; } @@ -472,7 +474,10 @@ zlog(ZLOG_STUFF, ZLOG_ALERT, "[pool %s] pm.start_servers(%d) must not be less than pm.min_spare_servers(%d) and not greater than pm.max_spare_servers(%d)", wp->config->name, config->pm_start_servers, config->pm_min_spare_servers, config->pm_max_spare_servers); return -1; } - + } else { + wp->config->pm_start_servers = 0; + wp->config->pm_min_spare_servers = 0; + wp->config->pm_max_spare_servers = 0; } Index: fpm_conf.h =================================================================== --- fpm_conf.h (revision 302051) +++ fpm_conf.h (working copy) @@ -67,7 +67,7 @@ intptr_t offset; }; -enum { PM_STYLE_STATIC = 1, PM_STYLE_DYNAMIC = 2 }; +enum { PM_STYLE_STATIC = 1, PM_STYLE_DYNAMIC = 2, PM_STYLE_ONDEMAND = 3 }; int fpm_conf_init_main(); int fpm_worker_pool_config_free(struct fpm_worker_pool_config_s *wpc); Index: fpm_process_ctl.c =================================================================== --- fpm_process_ctl.c (revision 302051) +++ fpm_process_ctl.c (working copy) @@ -351,6 +351,23 @@ /* update status structure for all PMs */ fpm_status_update_activity(wp->shm_status, idle, active, idle + active, 0); + /* this is specific to PM_STYLE_ONDEMAND */ + if (wp->config->pm == PM_STYLE_ONDEMAND) { + struct timeval last, now; + + zlog(ZLOG_STUFF, ZLOG_DEBUG, "[pool %s] currently %d active children, %d spare children", wp->config->name, active, idle); + + if (!last_idle_child) continue; + + fpm_request_last_activity(last_idle_child, &last); + fpm_clock_get(&now); + if (last.tv_sec < now.tv_sec - 10) { + last_idle_child->idle_kill = 1; + fpm_pctl_kill(last_idle_child->pid, FPM_PCTL_TERM); + } + continue; + } + /* the rest is only used by PM_STYLE_DYNAMIC */ if (wp->config->pm != PM_STYLE_DYNAMIC) continue; @@ -461,3 +478,35 @@ } /* }}} */ +void fpm_pctl_on_socket_accept(int fd, short which, void *arg) /* {{{ */ +{ + struct fpm_worker_pool_s *wp = (struct fpm_worker_pool_s *)arg; + struct fpm_child_s *child; + struct timeval now, diff; + + + if (fpm_globals.parent_pid != getpid()) { + /* prevent a event race condition when child process + * have not set up its own event loop */ + return; + } + + + fpm_clock_get(&now); + timersub(&now, &wp->last_fork, &diff); + // if we forked in the last 500us, do nothing + if (diff.tv_sec == 0 && diff.tv_usec < 500) return; + wp->last_fork.tv_sec = 0; + wp->last_fork.tv_usec = 0; + + for (child = wp->children; child; child = child->next) { + /* if there is at least on idle child, it will handle the connection, stop here */ + if (fpm_request_is_idle(child)) { + return; + } + } + fpm_clock_get(&wp->last_fork); + fpm_children_make(wp, 1, 1, 1, wp->base); + zlog(ZLOG_STUFF, ZLOG_DEBUG, "[pool %s] got accept without idle child available .... I forked, now=%d.%d", wp->config->name, now.tv_sec, now.tv_usec); +} +/* }}} */ Index: fpm_process_ctl.h =================================================================== --- fpm_process_ctl.h (revision 302051) +++ fpm_process_ctl.h (working copy) @@ -17,6 +17,7 @@ int fpm_pctl_kill(pid_t pid, int how); void fpm_pctl_heartbeat(int fd, short which, void *arg); void fpm_pctl_perform_idle_server_maintenance_heartbeat(int fd, short which, void *arg); +void fpm_pctl_on_socket_accept(int fd, short which, void *arg); int fpm_pctl_child_exited(); int fpm_pctl_init_main(); Index: fpm_request.c =================================================================== --- fpm_request.c (revision 302051) +++ fpm_request.c (working copy) @@ -167,3 +167,22 @@ return(!slot_c.accepted.tv_sec && !slot_c.accepted.tv_usec ? 1 : 0); } /* }}} */ + +int fpm_request_last_activity(struct fpm_child_s *child, struct timeval *tv) /* {{{ */ +{ + struct fpm_shm_slot_s *slot; + struct fpm_shm_slot_s slot_c; + + if (!tv) return -1; + + slot = fpm_shm_slot(child); + if (!fpm_shm_slots_acquire(slot, 1)) { + return -1; + } + + slot_c = *slot; + fpm_shm_slots_release(slot); + *tv = slot_c.tv; + return 1; +} +/* }}} */ Index: fpm_request.h =================================================================== --- fpm_request.h (revision 302051) +++ fpm_request.h (working copy) @@ -16,6 +16,7 @@ void fpm_request_check_timed_out(struct fpm_child_s *child, struct timeval *tv, int terminate_timeout, int slowlog_timeout); int fpm_request_is_idle(struct fpm_child_s *child); +int fpm_request_last_activity(struct fpm_child_s *child, struct timeval *tv); enum fpm_request_stage_e { FPM_REQUEST_ACCEPTING = 1, Index: fpm_worker_pool.h =================================================================== --- fpm_worker_pool.h (revision 302051) +++ fpm_worker_pool.h (working copy) @@ -38,6 +38,9 @@ int idle_spawn_rate; int warn_max_children; struct fpm_shm_s *shm_status; + struct event *socket_event; + struct event_base *base; + struct timeval last_fork; }; struct fpm_worker_pool_s *fpm_worker_pool_alloc(); |
Copyright © 2001-2024 The PHP Group All rights reserved. |
Last updated: Sat Dec 21 16:01:28 2024 UTC |