|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
Patch fpm-ondemand-pm for FPM related Bug #52569Patch version 2010-08-09 20:14 UTC Return to Bug #52569 | Download this patchThis patch is obsolete Obsoleted by patches:
Developer: fat@php.net
Index: fpm_request.h
===================================================================
--- fpm_request.h (revision 297735)
+++ 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_process_ctl.c
===================================================================
--- fpm_process_ctl.c (revision 297735)
+++ 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->style == 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->style != 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 297735)
+++ 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_conf.c
===================================================================
--- fpm_conf.c (revision 297735)
+++ fpm_conf.c (working copy)
@@ -86,6 +86,8 @@
c->style = PM_STYLE_STATIC;
} else if (!strcmp(value, "dynamic")) {
c->style = PM_STYLE_DYNAMIC;
+ } else if (!strcmp(value, "ondemand")) {
+ c->style = PM_STYLE_ONDEMAND;
} else {
return "invalid value for 'style'";
}
@@ -437,6 +439,10 @@
zlog(ZLOG_STUFF, ZLOG_ALERT, "[pool %s] start_servers(%d) must not be less than min_spare_servers(%d) and not greater than max_spare_servers(%d)", wp->config->name, pm->dynamic.start_servers, pm->dynamic.min_spare_servers, pm->dynamic.max_spare_servers);
return -1;
}
+ } else {
+ wp->config->pm->dynamic.start_servers = 0;
+ wp->config->pm->dynamic.min_spare_servers = 0;
+ wp->config->pm->dynamic.max_spare_servers = 0;
}
Index: fpm_conf.h
===================================================================
--- fpm_conf.h (revision 297735)
+++ fpm_conf.h (working copy)
@@ -67,7 +67,7 @@
unsigned catch_workers_output:1;
};
-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_worker_pool.h
===================================================================
--- fpm_worker_pool.h (revision 297735)
+++ fpm_worker_pool.h (working copy)
@@ -39,6 +39,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();
Index: fpm_request.c
===================================================================
--- fpm_request.c (revision 297735)
+++ 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_children.c
===================================================================
--- fpm_children.c (revision 297735)
+++ fpm_children.c (working copy)
@@ -361,6 +361,12 @@
} else {
max = wp->running_children + nb_to_spawn;
}
+ } else if (wp->config->pm->style == 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->style == 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);
}
/* }}} */
|
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Sat Oct 25 16:00:02 2025 UTC |