xref: /PHP-5.3/sapi/fpm/fpm/fpm_scoreboard.c (revision 4a0cd394)
1 
2 	/* $Id: fpm_status.c 312399 2011-06-23 08:03:52Z fat $ */
3 	/* (c) 2009 Jerome Loyet */
4 
5 #include "php.h"
6 #include "SAPI.h"
7 #include <stdio.h>
8 #include <time.h>
9 
10 #include "fpm_config.h"
11 #include "fpm_scoreboard.h"
12 #include "fpm_shm.h"
13 #include "fpm_sockets.h"
14 #include "fpm_worker_pool.h"
15 #include "fpm_clock.h"
16 #include "zlog.h"
17 
18 static struct fpm_scoreboard_s *fpm_scoreboard = NULL;
19 static int fpm_scoreboard_i = -1;
20 #ifdef HAVE_TIMES
21 static float fpm_scoreboard_tick;
22 #endif
23 
24 
fpm_scoreboard_init_main()25 int fpm_scoreboard_init_main() /* {{{ */
26 {
27 	struct fpm_worker_pool_s *wp;
28 	int i;
29 
30 #ifdef HAVE_TIMES
31 #if (defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK))
32 	fpm_scoreboard_tick = sysconf(_SC_CLK_TCK);
33 #else /* _SC_CLK_TCK */
34 #ifdef HZ
35 	fpm_scoreboard_tick = HZ;
36 #else /* HZ */
37 	fpm_scoreboard_tick = 100;
38 #endif /* HZ */
39 #endif /* _SC_CLK_TCK */
40 	zlog(ZLOG_DEBUG, "got clock tick '%.0f'", fpm_scoreboard_tick);
41 #endif /* HAVE_TIMES */
42 
43 
44 	for (wp = fpm_worker_all_pools; wp; wp = wp->next) {
45 		if (wp->config->pm_max_children < 1) {
46 			zlog(ZLOG_ERROR, "[pool %s] Unable to create scoreboard SHM because max_client is not set", wp->config->name);
47 			return -1;
48 		}
49 
50 		if (wp->scoreboard) {
51 			zlog(ZLOG_ERROR, "[pool %s] Unable to create scoreboard SHM because it already exists", wp->config->name);
52 			return -1;
53 		}
54 
55 		wp->scoreboard = fpm_shm_alloc(sizeof(struct fpm_scoreboard_s) + (wp->config->pm_max_children - 1) * sizeof(struct fpm_scoreboard_proc_s *));
56 		if (!wp->scoreboard) {
57 			return -1;
58 		}
59 		wp->scoreboard->nprocs = wp->config->pm_max_children;
60 		for (i = 0; i < wp->scoreboard->nprocs; i++) {
61 			wp->scoreboard->procs[i] = fpm_shm_alloc(sizeof(struct fpm_scoreboard_proc_s));
62 			if (!wp->scoreboard->procs[i]) {
63 				return -1;
64 			}
65 			memset(wp->scoreboard->procs[i], 0, sizeof(struct fpm_scoreboard_proc_s));
66 		}
67 
68 		wp->scoreboard->pm = wp->config->pm;
69 		wp->scoreboard->start_epoch = time(NULL);
70 		strlcpy(wp->scoreboard->pool, wp->config->name, sizeof(wp->scoreboard->pool));
71 	}
72 	return 0;
73 }
74 /* }}} */
75 
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)76 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) /* {{{ */
77 {
78 	if (!scoreboard) {
79 		scoreboard = fpm_scoreboard;
80 	}
81 	if (!scoreboard) {
82 		zlog(ZLOG_WARNING, "Unable to update scoreboard: the SHM has not been found");
83 		return;
84 	}
85 
86 
87 	fpm_spinlock(&scoreboard->lock, 0);
88 	if (action == FPM_SCOREBOARD_ACTION_SET) {
89 		if (idle >= 0) {
90 			scoreboard->idle = idle;
91 		}
92 		if (active >= 0) {
93 			scoreboard->active = active;
94 		}
95 		if (lq >= 0) {
96 			scoreboard->lq = lq;
97 		}
98 		if (lq_len >= 0) {
99 			scoreboard->lq_len = lq_len;
100 		}
101 #ifdef HAVE_FPM_LQ /* prevent unnecessary test */
102 		if (scoreboard->lq > scoreboard->lq_max) {
103 			scoreboard->lq_max = scoreboard->lq;
104 		}
105 #endif
106 		if (requests >= 0) {
107 			scoreboard->requests = requests;
108 		}
109 
110 		if (max_children_reached >= 0) {
111 			scoreboard->max_children_reached = max_children_reached;
112 		}
113 	} else {
114 		if (scoreboard->idle + idle > 0) {
115 			scoreboard->idle += idle;
116 		} else {
117 			scoreboard->idle = 0;
118 		}
119 
120 		if (scoreboard->active + active > 0) {
121 			scoreboard->active += active;
122 		} else {
123 			scoreboard->active = 0;
124 		}
125 
126 		if (scoreboard->requests + requests > 0) {
127 			scoreboard->requests += requests;
128 		} else {
129 			scoreboard->requests = 0;
130 		}
131 
132 		if (scoreboard->max_children_reached + max_children_reached > 0) {
133 			scoreboard->max_children_reached += max_children_reached;
134 		} else {
135 			scoreboard->max_children_reached = 0;
136 		}
137 	}
138 
139 	if (scoreboard->active > scoreboard->active_max) {
140 		scoreboard->active_max = scoreboard->active;
141 	}
142 
143 	fpm_unlock(scoreboard->lock);
144 }
145 /* }}} */
146 
fpm_scoreboard_get()147 struct fpm_scoreboard_s *fpm_scoreboard_get() /* {{{*/
148 {
149 	return fpm_scoreboard;
150 }
151 /* }}} */
152 
fpm_scoreboard_proc_get(struct fpm_scoreboard_s * scoreboard,int child_index)153 struct fpm_scoreboard_proc_s *fpm_scoreboard_proc_get(struct fpm_scoreboard_s *scoreboard, int child_index) /* {{{*/
154 {
155 	if (!scoreboard) {
156 		scoreboard = fpm_scoreboard;
157 	}
158 
159 	if (!scoreboard) {
160 		return NULL;
161 	}
162 
163 	if (child_index < 0) {
164 		child_index = fpm_scoreboard_i;
165 	}
166 
167 	if (child_index < 0 || child_index >= scoreboard->nprocs) {
168 		return NULL;
169 	}
170 
171 	return scoreboard->procs[child_index];
172 }
173 /* }}} */
174 
fpm_scoreboard_acquire(struct fpm_scoreboard_s * scoreboard,int nohang)175 struct fpm_scoreboard_s *fpm_scoreboard_acquire(struct fpm_scoreboard_s *scoreboard, int nohang) /* {{{ */
176 {
177 	struct fpm_scoreboard_s *s;
178 
179 	s = scoreboard ? scoreboard : fpm_scoreboard;
180 	if (!s) {
181 		return NULL;
182 	}
183 
184 	if (!fpm_spinlock(&s->lock, nohang)) {
185 		return NULL;
186 	}
187 	return s;
188 }
189 /* }}} */
190 
fpm_scoreboard_release(struct fpm_scoreboard_s * scoreboard)191 void fpm_scoreboard_release(struct fpm_scoreboard_s *scoreboard) {
192 	if (!scoreboard) {
193 		return;
194 	}
195 
196 	scoreboard->lock = 0;
197 }
198 
fpm_scoreboard_proc_acquire(struct fpm_scoreboard_s * scoreboard,int child_index,int nohang)199 struct fpm_scoreboard_proc_s *fpm_scoreboard_proc_acquire(struct fpm_scoreboard_s *scoreboard, int child_index, int nohang) /* {{{ */
200 {
201 	struct fpm_scoreboard_proc_s *proc;
202 
203 	proc = fpm_scoreboard_proc_get(scoreboard, child_index);
204 	if (!proc) {
205 		return NULL;
206 	}
207 
208 	if (!fpm_spinlock(&proc->lock, nohang)) {
209 		return NULL;
210 	}
211 
212 	return proc;
213 }
214 /* }}} */
215 
fpm_scoreboard_proc_release(struct fpm_scoreboard_proc_s * proc)216 void fpm_scoreboard_proc_release(struct fpm_scoreboard_proc_s *proc) /* {{{ */
217 {
218 	if (!proc) {
219 		return;
220 	}
221 
222 	proc->lock = 0;
223 }
224 
fpm_scoreboard_free(struct fpm_scoreboard_s * scoreboard)225 void fpm_scoreboard_free(struct fpm_scoreboard_s *scoreboard) /* {{{ */
226 {
227 	int i;
228 
229 	if (!scoreboard) {
230 		zlog(ZLOG_ERROR, "**scoreboard is NULL");
231 		return;
232 	}
233 
234 	for (i = 0; i < scoreboard->nprocs; i++) {
235 		if (!scoreboard->procs[i]) {
236 			continue;
237 		}
238 		fpm_shm_free(scoreboard->procs[i], sizeof(struct fpm_scoreboard_proc_s));
239 	}
240 	fpm_shm_free(scoreboard, sizeof(struct fpm_scoreboard_s));
241 }
242 /* }}} */
243 
fpm_scoreboard_child_use(struct fpm_scoreboard_s * scoreboard,int child_index,pid_t pid)244 void fpm_scoreboard_child_use(struct fpm_scoreboard_s *scoreboard, int child_index, pid_t pid) /* {{{ */
245 {
246 	struct fpm_scoreboard_proc_s *proc;
247 	fpm_scoreboard = scoreboard;
248 	fpm_scoreboard_i = child_index;
249 	proc = fpm_scoreboard_proc_get(scoreboard, child_index);
250 	if (!proc) {
251 		return;
252 	}
253 	proc->pid = pid;
254 	proc->start_epoch = time(NULL);
255 }
256 /* }}} */
257 
fpm_scoreboard_proc_free(struct fpm_scoreboard_s * scoreboard,int child_index)258 void fpm_scoreboard_proc_free(struct fpm_scoreboard_s *scoreboard, int child_index) /* {{{ */
259 {
260 	if (!scoreboard) {
261 		return;
262 	}
263 
264 	if (child_index < 0 || child_index >= scoreboard->nprocs) {
265 		return;
266 	}
267 
268 	if (scoreboard->procs[child_index] && scoreboard->procs[child_index]->used > 0) {
269 		memset(scoreboard->procs[child_index], 0, sizeof(struct fpm_scoreboard_proc_s));
270 	}
271 
272 	/* set this slot as free to avoid search on next alloc */
273 	scoreboard->free_proc = child_index;
274 }
275 /* }}} */
276 
fpm_scoreboard_proc_alloc(struct fpm_scoreboard_s * scoreboard,int * child_index)277 int fpm_scoreboard_proc_alloc(struct fpm_scoreboard_s *scoreboard, int *child_index) /* {{{ */
278 {
279 	int i = -1;
280 
281 	if (!scoreboard || !child_index) {
282 		return -1;
283 	}
284 
285 	/* first try the slot which is supposed to be free */
286 	if (scoreboard->free_proc >= 0 && scoreboard->free_proc < scoreboard->nprocs) {
287 		if (scoreboard->procs[scoreboard->free_proc] && !scoreboard->procs[scoreboard->free_proc]->used) {
288 			i = scoreboard->free_proc;
289 		}
290 	}
291 
292 	if (i < 0) { /* the supposed free slot is not, let's search for a free slot */
293 		zlog(ZLOG_DEBUG, "[pool %s] the proc->free_slot was not free. Let's search", scoreboard->pool);
294 		for (i = 0; i < scoreboard->nprocs; i++) {
295 			if (scoreboard->procs[i] && !scoreboard->procs[i]->used) { /* found */
296 				break;
297 			}
298 		}
299 	}
300 
301 	/* no free slot */
302 	if (i < 0 || i >= scoreboard->nprocs) {
303 		zlog(ZLOG_ERROR, "[pool %s] no free scoreboard slot", scoreboard->pool);
304 		return -1;
305 	}
306 
307 	scoreboard->procs[i]->used = 1;
308 	*child_index = i;
309 
310 	/* supposed next slot is free */
311 	if (i + 1 >= scoreboard->nprocs) {
312 		scoreboard->free_proc = 0;
313 	} else {
314 		scoreboard->free_proc = i + 1;
315 	}
316 
317 	return 0;
318 }
319 /* }}} */
320 
321 #ifdef HAVE_TIMES
fpm_scoreboard_get_tick()322 float fpm_scoreboard_get_tick() /* {{{ */
323 {
324 	return fpm_scoreboard_tick;
325 }
326 /* }}} */
327 #endif
328 
329