This source file includes following definitions.
- fpm_scoreboard_init_main
- fpm_scoreboard_update
- fpm_scoreboard_get
- fpm_scoreboard_proc_get
- fpm_scoreboard_acquire
- fpm_scoreboard_release
- fpm_scoreboard_proc_acquire
- fpm_scoreboard_proc_release
- fpm_scoreboard_free
- fpm_scoreboard_child_use
- fpm_scoreboard_proc_free
- fpm_scoreboard_proc_alloc
- fpm_scoreboard_get_tick
1
2
3
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
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
34 #ifdef HZ
35 fpm_scoreboard_tick = HZ;
36 #else
37 fpm_scoreboard_tick = 100;
38 #endif
39 #endif
40 zlog(ZLOG_DEBUG, "got clock tick '%.0f'", fpm_scoreboard_tick);
41 #endif
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
76 void fpm_scoreboard_update(int idle, int active, int lq, int lq_len, int requests, int max_children_reached, int slow_rq, 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
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 if (slow_rq > 0) {
114 scoreboard->slow_rq = slow_rq;
115 }
116 } else {
117 if (scoreboard->idle + idle > 0) {
118 scoreboard->idle += idle;
119 } else {
120 scoreboard->idle = 0;
121 }
122
123 if (scoreboard->active + active > 0) {
124 scoreboard->active += active;
125 } else {
126 scoreboard->active = 0;
127 }
128
129 if (scoreboard->requests + requests > 0) {
130 scoreboard->requests += requests;
131 } else {
132 scoreboard->requests = 0;
133 }
134
135 if (scoreboard->max_children_reached + max_children_reached > 0) {
136 scoreboard->max_children_reached += max_children_reached;
137 } else {
138 scoreboard->max_children_reached = 0;
139 }
140
141 if (scoreboard->slow_rq + slow_rq > 0) {
142 scoreboard->slow_rq += slow_rq;
143 } else {
144 scoreboard->slow_rq = 0;
145 }
146 }
147
148 if (scoreboard->active > scoreboard->active_max) {
149 scoreboard->active_max = scoreboard->active;
150 }
151
152 fpm_unlock(scoreboard->lock);
153 }
154
155
156 struct fpm_scoreboard_s *fpm_scoreboard_get()
157 {
158 return fpm_scoreboard;
159 }
160
161
162 struct fpm_scoreboard_proc_s *fpm_scoreboard_proc_get(struct fpm_scoreboard_s *scoreboard, int child_index)
163 {
164 if (!scoreboard) {
165 scoreboard = fpm_scoreboard;
166 }
167
168 if (!scoreboard) {
169 return NULL;
170 }
171
172 if (child_index < 0) {
173 child_index = fpm_scoreboard_i;
174 }
175
176 if (child_index < 0 || child_index >= scoreboard->nprocs) {
177 return NULL;
178 }
179
180 return scoreboard->procs[child_index];
181 }
182
183
184 struct fpm_scoreboard_s *fpm_scoreboard_acquire(struct fpm_scoreboard_s *scoreboard, int nohang)
185 {
186 struct fpm_scoreboard_s *s;
187
188 s = scoreboard ? scoreboard : fpm_scoreboard;
189 if (!s) {
190 return NULL;
191 }
192
193 if (!fpm_spinlock(&s->lock, nohang)) {
194 return NULL;
195 }
196 return s;
197 }
198
199
200 void fpm_scoreboard_release(struct fpm_scoreboard_s *scoreboard) {
201 if (!scoreboard) {
202 return;
203 }
204
205 scoreboard->lock = 0;
206 }
207
208 struct fpm_scoreboard_proc_s *fpm_scoreboard_proc_acquire(struct fpm_scoreboard_s *scoreboard, int child_index, int nohang)
209 {
210 struct fpm_scoreboard_proc_s *proc;
211
212 proc = fpm_scoreboard_proc_get(scoreboard, child_index);
213 if (!proc) {
214 return NULL;
215 }
216
217 if (!fpm_spinlock(&proc->lock, nohang)) {
218 return NULL;
219 }
220
221 return proc;
222 }
223
224
225 void fpm_scoreboard_proc_release(struct fpm_scoreboard_proc_s *proc)
226 {
227 if (!proc) {
228 return;
229 }
230
231 proc->lock = 0;
232 }
233
234 void fpm_scoreboard_free(struct fpm_scoreboard_s *scoreboard)
235 {
236 int i;
237
238 if (!scoreboard) {
239 zlog(ZLOG_ERROR, "**scoreboard is NULL");
240 return;
241 }
242
243 for (i = 0; i < scoreboard->nprocs; i++) {
244 if (!scoreboard->procs[i]) {
245 continue;
246 }
247 fpm_shm_free(scoreboard->procs[i], sizeof(struct fpm_scoreboard_proc_s));
248 }
249 fpm_shm_free(scoreboard, sizeof(struct fpm_scoreboard_s));
250 }
251
252
253 void fpm_scoreboard_child_use(struct fpm_scoreboard_s *scoreboard, int child_index, pid_t pid)
254 {
255 struct fpm_scoreboard_proc_s *proc;
256 fpm_scoreboard = scoreboard;
257 fpm_scoreboard_i = child_index;
258 proc = fpm_scoreboard_proc_get(scoreboard, child_index);
259 if (!proc) {
260 return;
261 }
262 proc->pid = pid;
263 proc->start_epoch = time(NULL);
264 }
265
266
267 void fpm_scoreboard_proc_free(struct fpm_scoreboard_s *scoreboard, int child_index)
268 {
269 if (!scoreboard) {
270 return;
271 }
272
273 if (child_index < 0 || child_index >= scoreboard->nprocs) {
274 return;
275 }
276
277 if (scoreboard->procs[child_index] && scoreboard->procs[child_index]->used > 0) {
278 memset(scoreboard->procs[child_index], 0, sizeof(struct fpm_scoreboard_proc_s));
279 }
280
281
282 scoreboard->free_proc = child_index;
283 }
284
285
286 int fpm_scoreboard_proc_alloc(struct fpm_scoreboard_s *scoreboard, int *child_index)
287 {
288 int i = -1;
289
290 if (!scoreboard || !child_index) {
291 return -1;
292 }
293
294
295 if (scoreboard->free_proc >= 0 && scoreboard->free_proc < scoreboard->nprocs) {
296 if (scoreboard->procs[scoreboard->free_proc] && !scoreboard->procs[scoreboard->free_proc]->used) {
297 i = scoreboard->free_proc;
298 }
299 }
300
301 if (i < 0) {
302 zlog(ZLOG_DEBUG, "[pool %s] the proc->free_slot was not free. Let's search", scoreboard->pool);
303 for (i = 0; i < scoreboard->nprocs; i++) {
304 if (scoreboard->procs[i] && !scoreboard->procs[i]->used) {
305 break;
306 }
307 }
308 }
309
310
311 if (i < 0 || i >= scoreboard->nprocs) {
312 zlog(ZLOG_ERROR, "[pool %s] no free scoreboard slot", scoreboard->pool);
313 return -1;
314 }
315
316 scoreboard->procs[i]->used = 1;
317 *child_index = i;
318
319
320 if (i + 1 >= scoreboard->nprocs) {
321 scoreboard->free_proc = 0;
322 } else {
323 scoreboard->free_proc = i + 1;
324 }
325
326 return 0;
327 }
328
329
330 #ifdef HAVE_TIMES
331 float fpm_scoreboard_get_tick()
332 {
333 return fpm_scoreboard_tick;
334 }
335
336 #endif
337