Back to index

php5  5.3.10
fpm_scoreboard.c
Go to the documentation of this file.
00001 
00002        /* $Id: fpm_status.c 312399 2011-06-23 08:03:52Z fat $ */
00003        /* (c) 2009 Jerome Loyet */
00004 
00005 #include "php.h"
00006 #include "SAPI.h"
00007 #include <stdio.h>
00008 #include <time.h>
00009 
00010 #include "fpm_config.h"
00011 #include "fpm_scoreboard.h"
00012 #include "fpm_shm.h"
00013 #include "fpm_sockets.h"
00014 #include "fpm_worker_pool.h"
00015 #include "fpm_clock.h"
00016 #include "zlog.h"
00017 
00018 static struct fpm_scoreboard_s *fpm_scoreboard = NULL;
00019 static int fpm_scoreboard_i = -1;
00020 #ifdef HAVE_TIMES
00021 static float fpm_scoreboard_tick;
00022 #endif
00023 
00024 
00025 int fpm_scoreboard_init_main() /* {{{ */
00026 {
00027        struct fpm_worker_pool_s *wp;
00028        int i;
00029 
00030 #ifdef HAVE_TIMES
00031 #if (defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK))
00032        fpm_scoreboard_tick = sysconf(_SC_CLK_TCK);
00033 #else /* _SC_CLK_TCK */
00034 #ifdef HZ
00035        fpm_scoreboard_tick = HZ;
00036 #else /* HZ */
00037        fpm_scoreboard_tick = 100;
00038 #endif /* HZ */
00039 #endif /* _SC_CLK_TCK */
00040        zlog(ZLOG_DEBUG, "got clock tick '%.0f'", fpm_scoreboard_tick);
00041 #endif /* HAVE_TIMES */
00042 
00043 
00044        for (wp = fpm_worker_all_pools; wp; wp = wp->next) {
00045               if (wp->config->pm_max_children < 1) {
00046                      zlog(ZLOG_ERROR, "[pool %s] Unable to create scoreboard SHM because max_client is not set", wp->config->name);
00047                      return -1;
00048               }
00049 
00050               if (wp->scoreboard) {
00051                      zlog(ZLOG_ERROR, "[pool %s] Unable to create scoreboard SHM because it already exists", wp->config->name);
00052                      return -1;
00053               }
00054 
00055               wp->scoreboard = fpm_shm_alloc(sizeof(struct fpm_scoreboard_s) + (wp->config->pm_max_children - 1) * sizeof(struct fpm_scoreboard_proc_s *));
00056               if (!wp->scoreboard) {
00057                      return -1;
00058               }
00059               wp->scoreboard->nprocs = wp->config->pm_max_children;
00060               for (i = 0; i < wp->scoreboard->nprocs; i++) {
00061                      wp->scoreboard->procs[i] = fpm_shm_alloc(sizeof(struct fpm_scoreboard_proc_s));
00062                      if (!wp->scoreboard->procs[i]) {
00063                             return -1;
00064                      }
00065                      memset(wp->scoreboard->procs[i], 0, sizeof(struct fpm_scoreboard_proc_s));
00066               }
00067 
00068               wp->scoreboard->pm = wp->config->pm;
00069               wp->scoreboard->start_epoch = time(NULL);
00070               strlcpy(wp->scoreboard->pool, wp->config->name, sizeof(wp->scoreboard->pool));
00071        }
00072        return 0;     
00073 }
00074 /* }}} */
00075 
00076 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) /* {{{ */
00077 {
00078        if (!scoreboard) {
00079               scoreboard = fpm_scoreboard;
00080        }
00081        if (!scoreboard) {
00082               zlog(ZLOG_WARNING, "Unable to update scoreboard: the SHM has not been found");
00083               return;
00084        }
00085 
00086 
00087        fpm_spinlock(&scoreboard->lock, 0);
00088        if (action == FPM_SCOREBOARD_ACTION_SET) {
00089               if (idle >= 0) {
00090                      scoreboard->idle = idle;
00091               }
00092               if (active >= 0) {
00093                      scoreboard->active = active;
00094               }
00095               if (lq >= 0) {
00096                      scoreboard->lq = lq;
00097               }
00098               if (lq_len >= 0) {
00099                      scoreboard->lq_len = lq_len;
00100               }
00101 #ifdef HAVE_FPM_LQ /* prevent unnecessary test */
00102               if (scoreboard->lq > scoreboard->lq_max) {
00103                      scoreboard->lq_max = scoreboard->lq;
00104               }
00105 #endif
00106               if (requests >= 0) {
00107                      scoreboard->requests = requests;
00108               }
00109 
00110               if (max_children_reached >= 0) {
00111                      scoreboard->max_children_reached = max_children_reached;
00112               }
00113        } else {
00114               if (scoreboard->idle + idle > 0) {
00115                      scoreboard->idle += idle;
00116               } else {
00117                      scoreboard->idle = 0;
00118               }
00119 
00120               if (scoreboard->active + active > 0) {
00121                      scoreboard->active += active;
00122               } else {
00123                      scoreboard->active = 0;
00124               }
00125 
00126               if (scoreboard->requests + requests > 0) {
00127                      scoreboard->requests += requests;
00128               } else {
00129                      scoreboard->requests = 0;
00130               }
00131 
00132               if (scoreboard->max_children_reached + max_children_reached > 0) {
00133                      scoreboard->max_children_reached += max_children_reached;
00134               } else {
00135                      scoreboard->max_children_reached = 0;
00136               }
00137        }
00138 
00139        if (scoreboard->active > scoreboard->active_max) {
00140               scoreboard->active_max = scoreboard->active;
00141        }
00142 
00143        fpm_unlock(scoreboard->lock);
00144 }
00145 /* }}} */
00146 
00147 struct fpm_scoreboard_s *fpm_scoreboard_get() /* {{{*/
00148 {
00149        return fpm_scoreboard;
00150 }
00151 /* }}} */
00152 
00153 struct fpm_scoreboard_proc_s *fpm_scoreboard_proc_get(struct fpm_scoreboard_s *scoreboard, int child_index) /* {{{*/
00154 {
00155        if (!scoreboard) {
00156               scoreboard = fpm_scoreboard;
00157        }
00158 
00159        if (!scoreboard) {
00160               return NULL;
00161        }
00162 
00163        if (child_index < 0) {
00164               child_index = fpm_scoreboard_i;
00165        }
00166 
00167        if (child_index < 0 || child_index >= scoreboard->nprocs) {
00168               return NULL;
00169        }
00170 
00171        return scoreboard->procs[child_index];
00172 }
00173 /* }}} */
00174 
00175 struct fpm_scoreboard_s *fpm_scoreboard_acquire(struct fpm_scoreboard_s *scoreboard, int nohang) /* {{{ */
00176 {
00177        struct fpm_scoreboard_s *s;
00178 
00179        s = scoreboard ? scoreboard : fpm_scoreboard;
00180        if (!s) {
00181               return NULL;
00182        }
00183 
00184        if (!fpm_spinlock(&s->lock, nohang)) {
00185               return NULL;
00186        }
00187        return s;
00188 }
00189 /* }}} */
00190 
00191 void fpm_scoreboard_release(struct fpm_scoreboard_s *scoreboard) {
00192        if (!scoreboard) {
00193               return;
00194        }
00195 
00196        scoreboard->lock = 0;
00197 }
00198 
00199 struct fpm_scoreboard_proc_s *fpm_scoreboard_proc_acquire(struct fpm_scoreboard_s *scoreboard, int child_index, int nohang) /* {{{ */
00200 {
00201        struct fpm_scoreboard_proc_s *proc;
00202 
00203        proc = fpm_scoreboard_proc_get(scoreboard, child_index);
00204        if (!proc) {
00205               return NULL;
00206        }
00207 
00208        if (!fpm_spinlock(&proc->lock, nohang)) {
00209               return NULL;
00210        }
00211 
00212        return proc;
00213 }
00214 /* }}} */
00215 
00216 void fpm_scoreboard_proc_release(struct fpm_scoreboard_proc_s *proc) /* {{{ */
00217 {
00218        if (!proc) {
00219               return;
00220        }
00221 
00222        proc->lock = 0;
00223 }
00224 
00225 void fpm_scoreboard_free(struct fpm_scoreboard_s *scoreboard) /* {{{ */
00226 {
00227        int i;
00228 
00229        if (!scoreboard) {
00230               zlog(ZLOG_ERROR, "**scoreboard is NULL");
00231               return;
00232        }
00233 
00234        for (i = 0; i < scoreboard->nprocs; i++) {
00235               if (!scoreboard->procs[i]) {
00236                      continue;
00237               }
00238               fpm_shm_free(scoreboard->procs[i], sizeof(struct fpm_scoreboard_proc_s));
00239        }
00240        fpm_shm_free(scoreboard, sizeof(struct fpm_scoreboard_s));
00241 }
00242 /* }}} */
00243 
00244 void fpm_scoreboard_child_use(struct fpm_scoreboard_s *scoreboard, int child_index, pid_t pid) /* {{{ */
00245 {
00246        struct fpm_scoreboard_proc_s *proc;
00247        fpm_scoreboard = scoreboard;
00248        fpm_scoreboard_i = child_index;
00249        proc = fpm_scoreboard_proc_get(scoreboard, child_index);
00250        if (!proc) {
00251               return;
00252        }
00253        proc->pid = pid;
00254        proc->start_epoch = time(NULL);
00255 }
00256 /* }}} */
00257 
00258 void fpm_scoreboard_proc_free(struct fpm_scoreboard_s *scoreboard, int child_index) /* {{{ */
00259 {
00260        if (!scoreboard) {
00261               return;
00262        }
00263 
00264        if (child_index < 0 || child_index >= scoreboard->nprocs) {
00265               return;
00266        }
00267 
00268        if (scoreboard->procs[child_index] && scoreboard->procs[child_index]->used > 0) {
00269               memset(scoreboard->procs[child_index], 0, sizeof(struct fpm_scoreboard_proc_s));
00270        }
00271 
00272        /* set this slot as free to avoid search on next alloc */
00273        scoreboard->free_proc = child_index;
00274 }
00275 /* }}} */
00276 
00277 int fpm_scoreboard_proc_alloc(struct fpm_scoreboard_s *scoreboard, int *child_index) /* {{{ */
00278 {
00279        int i = -1;
00280 
00281        if (!scoreboard || !child_index) {
00282               return -1;
00283        }
00284 
00285        /* first try the slot which is supposed to be free */
00286        if (scoreboard->free_proc >= 0 && scoreboard->free_proc < scoreboard->nprocs) {
00287               if (scoreboard->procs[scoreboard->free_proc] && !scoreboard->procs[scoreboard->free_proc]->used) {
00288                      i = scoreboard->free_proc;
00289               }
00290        }
00291 
00292        if (i < 0) { /* the supposed free slot is not, let's search for a free slot */
00293               zlog(ZLOG_DEBUG, "[pool %s] the proc->free_slot was not free. Let's search", scoreboard->pool);
00294               for (i = 0; i < scoreboard->nprocs; i++) {
00295                      if (scoreboard->procs[i] && !scoreboard->procs[i]->used) { /* found */
00296                             break;
00297                      }
00298               }
00299        }
00300 
00301        /* no free slot */
00302        if (i < 0 || i >= scoreboard->nprocs) {
00303               zlog(ZLOG_ERROR, "[pool %s] no free scoreboard slot", scoreboard->pool);
00304               return -1;
00305        }
00306 
00307        scoreboard->procs[i]->used = 1;
00308        *child_index = i;
00309 
00310        /* supposed next slot is free */
00311        if (i + 1 >= scoreboard->nprocs) {
00312               scoreboard->free_proc = 0;
00313        } else {
00314               scoreboard->free_proc = i + 1;
00315        }
00316 
00317        return 0;
00318 }
00319 /* }}} */
00320 
00321 #ifdef HAVE_TIMES
00322 float fpm_scoreboard_get_tick() /* {{{ */
00323 {
00324        return fpm_scoreboard_tick;
00325 }
00326 /* }}} */
00327 #endif
00328