dgaudet     97/09/12 13:37:39

  Modified:    src      CHANGES
               src/main http_log.c http_main.c scoreboard.h
               src/modules/standard mod_log_config.c mod_status.c
  Log:
    *) API: the short_score record has been split into two pieces, one which
       the parent writes on, and one which the child writes on.  As part of
       this change the get_scoreboard_info() function was removed, and
       scoreboard_image was exported.  This change fixes a race condition
       in filebased scoreboard systems, and speeds up changes involving the
       scoreboard in earlier 1.3 development.  [Dean Gaudet]
  
    *) If BUFFERED_LOGS is defined then mod_log_config will do atomic
       buffered writes -- that is, it will buffer up to PIPE_BUF (i.e. 4k)
       bytes before writing, but it will never split a log entry across a
       buffer boundary.  [Dean Gaudet]
  
  Revision  Changes    Path
  1.437     +7 -0      apachen/src/CHANGES
  
  Index: CHANGES
  ===================================================================
  RCS file: /export/home/cvs/apachen/src/CHANGES,v
  retrieving revision 1.436
  retrieving revision 1.437
  diff -u -r1.436 -r1.437
  --- CHANGES   1997/09/12 20:13:03     1.436
  +++ CHANGES   1997/09/12 20:37:30     1.437
  @@ -1,5 +1,12 @@
   Changes with Apache 1.3b1
   
  +  *) API: the short_score record has been split into two pieces, one which
  +     the parent writes on, and one which the child writes on.  As part of
  +     this change the get_scoreboard_info() function was removed, and
  +     scoreboard_image was exported.  This change fixes a race condition
  +     in filebased scoreboard systems, and speeds up changes involving the
  +     scoreboard in earlier 1.3 development.  [Dean Gaudet]
  +
     *) API: New register_other_child() API (see http_main.h) which allows
        modules to register children with the parent for maintenance.  It
        is disabled by defining NO_OTHER_CHILD.  [Dean Gaudet]
  
  
  
  1.34      +0 -2      apachen/src/main/http_log.c
  
  Index: http_log.c
  ===================================================================
  RCS file: /export/home/cvs/apachen/src/main/http_log.c,v
  retrieving revision 1.33
  retrieving revision 1.34
  diff -u -r1.33 -r1.34
  --- http_log.c        1997/09/12 20:13:08     1.33
  +++ http_log.c        1997/09/12 20:37:33     1.34
  @@ -400,7 +400,6 @@
   static void piped_log_maintenance (int reason, void *data, int status)
   {
       piped_log *pl = data;
  -    int pid;
   
       switch (reason) {
       case OC_REASON_DEATH:
  @@ -464,7 +463,6 @@
   API_EXPORT(piped_log *) open_piped_log (pool *p, const char *program)
   {
       piped_log *pl;
  -    int pid;
   
       pl = palloc (p, sizeof (*pl));
       pl->p = p;
  
  
  
  1.219     +68 -65    apachen/src/main/http_main.c
  
  Index: http_main.c
  ===================================================================
  RCS file: /export/home/cvs/apachen/src/main/http_main.c,v
  retrieving revision 1.218
  retrieving revision 1.219
  diff -u -r1.218 -r1.219
  --- http_main.c       1997/09/12 20:13:10     1.218
  +++ http_main.c       1997/09/12 20:37:34     1.219
  @@ -255,7 +255,7 @@
   static int my_child_num;
   #endif
   
  -static scoreboard *scoreboard_image = NULL;
  +scoreboard *scoreboard_image = NULL;
   
   /* small utility macros to make things easier to read */
   
  @@ -1538,7 +1538,7 @@
    * anyway.
    */
   
  -API_EXPORT(void) sync_scoreboard_image (void)
  +inline void sync_scoreboard_image (void)
   {
   #ifdef SCOREBOARD_FILE
       lseek (scoreboard_fd, 0L, 0);
  @@ -1548,7 +1548,7 @@
   
   #endif /* MULTITHREAD */
   
  -API_EXPORT(int) exists_scoreboard_image (void)
  +int exists_scoreboard_image (void)
   {
       return (scoreboard_image ? 1 : 0);
   }
  @@ -1573,17 +1573,14 @@
       sync_scoreboard_image();
       ss = &scoreboard_image->servers[child_num];
       old_status = ss->status;
  -    ss->x.pid = my_pid;
       ss->status = status;
   #ifdef OPTIMIZE_TIMEOUTS
       ++ss->cur_vtime;
   #endif
   
   #if defined(STATUS)
  -#ifdef OPTIMIZE_TIMEOUTS
  -    ss->last_used = ss->last_rtime;  /* close enough */
  -#else
  -    ss->last_used=time(NULL);
  +#ifndef OPTIMIZE_TIMEOUTS
  +    ss->last_used = time(NULL);
   #endif
       if (status == SERVER_READY || status == SERVER_DEAD) {
        /*
  @@ -1628,11 +1625,6 @@
   #endif
   }
   
  -API_EXPORT(short_score) get_scoreboard_info(int i)
  -{
  -    return (scoreboard_image->servers[i]);
  -}
  -
   #if defined(STATUS)
   void time_process_request (int child_num, int status)
   {
  @@ -1709,7 +1701,7 @@
       int i;
   
       for (i = 0; i < max_daemons_limit; ++i)
  -     if (scoreboard_image->servers[i].x.pid == pid)
  +     if (scoreboard_image->parent[i].pid == pid)
            return i;
   
       return -1;
  @@ -1745,13 +1737,13 @@
        /* now see who is done */
        not_dead_yet = 0;
        for (i = 0; i < max_daemons_limit; ++i) {
  -         int pid = scoreboard_image->servers[i].x.pid;
  +         int pid = scoreboard_image->parent[i].pid;
   
            if (pid == my_pid || pid == 0) continue;
   
            waitret = waitpid (pid, &status, WNOHANG);
            if (waitret == pid || waitret == -1) {
  -             scoreboard_image->servers[i].x.pid = 0;
  +             scoreboard_image->parent[i].pid = 0;
                continue;
            }
            ++not_dead_yet;
  @@ -1831,9 +1823,9 @@
   
       for (n = 0; n < max_daemons_limit; ++n) {
        if (scoreboard_image->servers[n].status != SERVER_DEAD
  -         && waitpid (scoreboard_image->servers[n].x.pid, &status, WNOHANG)
  -             == -1
  -         && errno == ECHILD) {
  +             && waitpid (scoreboard_image->parent[n].pid, &status, WNOHANG)
  +                 == -1
  +             && errno == ECHILD) {
            sync_scoreboard_image ();
            update_child_status (n, SERVER_DEAD, NULL);
            ret = 1;
  @@ -1870,7 +1862,7 @@
               if(scoreboard_image->servers[pi].status != SERVER_DEAD)
               {
                   e[hi] = pi;
  -                h[hi++] = (HANDLE)scoreboard_image->servers[pi].x.pid;
  +                h[hi++] = (HANDLE)scoreboard_image->parent[pi].pid;
               }
   
           }
  @@ -1880,9 +1872,9 @@
               if(rv == -1)
                   err = GetLastError();
               if((WAIT_OBJECT_0 <= (unsigned int)rv) && ((unsigned int)rv < 
(WAIT_OBJECT_0 + hi)))
  -                return(scoreboard_image->servers[e[rv - 
WAIT_OBJECT_0]].x.pid);
  +                return(scoreboard_image->parent[e[rv - WAIT_OBJECT_0]].pid);
               else if((WAIT_ABANDONED_0 <= (unsigned int)rv) && ((unsigned 
int)rv < (WAIT_ABANDONED_0 + hi)))
  -                return(scoreboard_image->servers[e[rv - 
WAIT_ABANDONED_0]].x.pid);
  +                return(scoreboard_image->parent[e[rv - 
WAIT_ABANDONED_0]].pid);
   
           }
       }
  @@ -3052,7 +3044,7 @@
       }    
   }
   
  -static int make_child(server_rec *s, int slot)
  +static int make_child(server_rec *s, int slot, time_t now)
   {
       int pid;
   
  @@ -3099,14 +3091,15 @@
        child_main (slot);
       }
   
  -    /* If the parent proceeds with a restart before the child has written
  -     * their pid into the scoreboard we'll end up "forgetting" about the
  -     * child.  So we write the child pid into the scoreboard now.  (This
  -     * is safe, because the child is going to be writing the same value
  -     * to the same word.)
  -     * XXX: this needs to be sync'd to disk in the non shared memory stuff
  -     */
  -    scoreboard_image->servers[slot].x.pid = pid;
  +#ifdef OPTIMIZE_TIMEOUTS
  +    scoreboard_image->parent[slot].last_rtime = now;
  +#endif
  +    scoreboard_image->parent[slot].pid = pid;
  +#ifdef SCOREBOARD_FILE
  +    lseek(scoreboard_fd, XtOffsetOf(scoreboard, parent[slot]), 0);
  +    force_write(scoreboard_fd, &scoreboard_image->parent[slot],
  +     sizeof(parent_score));
  +#endif
   
       return 0;
   }
  @@ -3116,12 +3109,13 @@
   static void startup_children (int number_to_start)
   {
       int i;
  +    time_t now = time(0);
   
       for (i = 0; number_to_start && i < daemons_limit; ++i ) {
        if (scoreboard_image->servers[i].status != SERVER_DEAD) {
            continue;
        }
  -     if (make_child (server_conf, i) < 0) {
  +     if (make_child (server_conf, i, now) < 0) {
            break;
        }
        --number_to_start;
  @@ -3146,26 +3140,30 @@
       int i;
       int to_kill;
       int idle_count;
  -    int free_head;
  -    int *free_ptr;
  -    int free_length;
       short_score *ss;
  -#ifdef OPTIMIZE_TIMEOUTS
       time_t now = time(0);
  -#endif
  +    int free_length;
  +    int free_slots[MAX_SPAWN_RATE];
  +    int last_non_dead;
   
       /* initialize the free_list */
  -    free_head = -1;
  -    free_ptr = &free_head;
       free_length = 0;
   
       to_kill = -1;
       idle_count = 0;
  +    last_non_dead = -1;
   
       sync_scoreboard_image ();
       for (i = 0; i < daemons_limit; ++i) {
  +     if (i >= max_daemons_limit && free_length == idle_spawn_rate) break;
        ss = &scoreboard_image->servers[i];
        switch (ss->status) {
  +         /* We consider a starting server as idle because we started it
  +          * at least a cycle ago, and if it still hasn't finished starting
  +          * then we're just going to swamp things worse by forking more.
  +          * So we hopefully won't need to fork more if we count it.
  +          */
  +     case SERVER_STARTING:
        case SERVER_READY:
            ++idle_count;
            /* always kill the highest numbered child if we have to...
  @@ -3179,39 +3177,43 @@
        case SERVER_DEAD:
            /* try to keep children numbers as low as possible */
            if (free_length < idle_spawn_rate) {
  -             *free_ptr = i;
  -             free_ptr = &scoreboard_image->servers[i].x.free_list;
  +             free_slots[free_length] = i;
                ++free_length;
            }
            break;
        }
  +     if (ss->status != SERVER_DEAD) {
  +         last_non_dead = i;
   #ifdef OPTIMIZE_TIMEOUTS
  -     if (ss->status != SERVER_DEAD && ss->timeout_len) {
  -         /* if it's a live server, with a live timeout then start checking
  -          * its timeout */
  -         if (ss->cur_vtime != ss->last_vtime) {
  -             /* it has made progress, so update its last_rtime, last_vtime */
  -             ss->last_rtime = now;
  -             ss->last_vtime = ss->cur_vtime;
  -         } else if (ss->last_rtime + ss->timeout_len < now) {
  -             /* no progress, and the timeout length has been exceeded */
  -             ss->timeout_len = 0;
  -             kill (ss->x.pid, SIGALRM);
  +         if (ss->timeout_len) {
  +             /* if it's a live server, with a live timeout then
  +              * start checking its timeout */
  +             parent_score *ps = &scoreboard_image->parent[i];
  +             if (ss->cur_vtime != ps->last_vtime) {
  +                 /* it has made progress, so update its last_rtime,
  +                  * last_vtime */
  +                 ps->last_rtime = now;
  +                 ps->last_vtime = ss->cur_vtime;
  +             } else if (ps->last_rtime + ss->timeout_len < now) {
  +                 /* no progress, and the timeout length has been exceeded */
  +                 ss->timeout_len = 0;
  +                 kill (ps->pid, SIGALRM);
  +             }
            }
  -     }
   #endif
  +     }
       }
  +    max_daemons_limit = last_non_dead + 1;
       if (idle_count > daemons_max_free) {
        /* kill off one child... we use SIGUSR1 because that'll cause it to
         * shut down gracefully, in case it happened to pick up a request
         * while we were counting
         */
  -     kill (scoreboard_image->servers[to_kill].x.pid, SIGUSR1);
  +     kill (scoreboard_image->parent[to_kill].pid, SIGUSR1);
        idle_spawn_rate = 1;
       } else if (idle_count < daemons_min_free) {
        /* terminate the free list */
  -     *free_ptr = -1;
  -     if (free_head == -1) {
  +     if (free_length == 0) {
            /* only report this condition once */
            static int reported = 0;
   
  @@ -3221,6 +3223,7 @@
                            " raising the MaxClients setting");
                reported = 1;
            }
  +         idle_spawn_rate = 1;
        } else {
            if (idle_spawn_rate >= 4) {
                aplog_error(APLOG_MARK, APLOG_ERR, server_conf,
  @@ -3228,12 +3231,8 @@
                            "to increase StartServers, or Min/MaxSpareServers)",
                            idle_spawn_rate);
            }
  -         i = 0;
  -         while (i < idle_spawn_rate && free_head != -1) {
  -             int slot = free_head;
  -             free_head = scoreboard_image->servers[free_head].x.free_list;
  -             make_child (server_conf, slot);
  -             ++i;
  +         for (i = 0; i < free_length; ++i) {
  +             make_child (server_conf, free_slots[i], now);
            }
            /* the next time around we want to spawn twice as many if this
             * wasn't good enough, but not if we've just done a graceful
  @@ -3358,10 +3357,8 @@
                        /* we're still doing a 1-for-1 replacement of dead
                         * children with new children
                         */
  -                     make_child (server_conf, child_slot);
  +                     make_child (server_conf, child_slot, time(0));
                        --remaining_children_to_start;
  -                     /* don't perform idle maintenance yet */
  -                     continue;
                    }
   #ifndef NO_OTHER_CHILD
                } else if (reap_other_child (pid, status) == 0) {
  @@ -3375,6 +3372,12 @@
                    aplog_error(APLOG_MARK, APLOG_WARNING, server_conf,
                                "long lost child came home! (pid %d)", pid );
                }
  +             /* Don't perform idle maintenance when a child dies,
  +              * only do it when there's a timeout.  Remember only a
  +              * finite number of children can die, and it's pretty
  +              * pathological for a lot to die suddenly.
  +              */
  +             continue;
            } else if (remaining_children_to_start) {
                /* we hit a 1 second timeout in which none of the previous
                 * generation of children needed to be reaped... so assume
  
  
  
  1.30      +18 -9     apachen/src/main/scoreboard.h
  
  Index: scoreboard.h
  ===================================================================
  RCS file: /export/home/cvs/apachen/src/main/scoreboard.h,v
  retrieving revision 1.29
  retrieving revision 1.30
  diff -u -r1.29 -r1.30
  --- scoreboard.h      1997/09/11 19:32:44     1.29
  +++ scoreboard.h      1997/09/12 20:37:35     1.30
  @@ -74,6 +74,7 @@
   #define SERVER_BUSY_LOG 6       /* Logging the request */
   #define SERVER_BUSY_DNS 7       /* Looking up a hostname */
   #define SERVER_GRACEFUL 8    /* server is gracefully finishing request */
  +#define SERVER_NUM_STATUS 9  /* number of status settings */
   
   /* A "virtual time" is simply a counter that indicates that a child is
    * making progress.  The parent checks up on each child, and when they have
  @@ -90,14 +91,9 @@
    */
   typedef unsigned vtime_t;
   
  +/* stuff which the children generally write, and the parent mainly reads */
   typedef struct {
  -    union {
  -     pid_t pid;              /* if it's not DEAD then this is the pid */
  -     int free_list;          /* otherwise this is scratch space */
  -    } x;
   #ifdef OPTIMIZE_TIMEOUTS
  -    vtime_t last_vtime;              /* the last vtime the parent has seen */
  -    time_t last_rtime;               /* time(0) of the last change */
       vtime_t cur_vtime;               /* the child's current vtime */
       unsigned short timeout_len;      /* length of the timeout */
   #endif
  @@ -119,7 +115,9 @@
   #ifndef NO_TIMES
       struct tms times;
   #endif
  +#ifndef OPTIMIZE_TIMEOUTS
       time_t last_used;
  +#endif
       char client[32]; /* Keep 'em small... */
       char request[64];        /* We just want an idea... */
       char vhost[32];     /* What virtual host is being accessed? */
  @@ -132,17 +130,28 @@
                                   restart is required */
       } global_score;
   
  +/* stuff which the parent generally writes and the children rarely read */
  +typedef struct {
  +    pid_t pid;
  +#ifdef OPTIMIZE_TIMEOUTS
  +    time_t last_rtime;               /* time(0) of the last change */
  +    vtime_t last_vtime;              /* the last vtime the parent has seen */
  +#endif
  +} parent_score;
  +
   typedef struct
       {
       short_score servers[HARD_SERVER_LIMIT];
  +    parent_score parent[HARD_SERVER_LIMIT];
       global_score global;
       } scoreboard;
   
   #define SCOREBOARD_SIZE              sizeof(scoreboard)
   
  -API_EXPORT(void) sync_scoreboard_image(void);
  -API_EXPORT(short_score) get_scoreboard_info(int x);
  -API_EXPORT(int) exists_scoreboard_image (void);
  +void sync_scoreboard_image(void);
  +int exists_scoreboard_image (void);
  +
  +extern scoreboard *scoreboard_image;
   
   /* for time_process_request() in http_main.c */
   #define START_PREQUEST 1
  
  
  
  1.39      +79 -4     apachen/src/modules/standard/mod_log_config.c
  
  Index: mod_log_config.c
  ===================================================================
  RCS file: /export/home/cvs/apachen/src/modules/standard/mod_log_config.c,v
  retrieving revision 1.38
  retrieving revision 1.39
  diff -u -r1.38 -r1.39
  --- mod_log_config.c  1997/09/12 20:13:24     1.38
  +++ mod_log_config.c  1997/09/12 20:37:38     1.39
  @@ -165,6 +165,7 @@
   #include "http_config.h"
   #include "http_core.h" /* For REMOTE_NAME */
   #include "http_log.h"
  +#include <limits.h>
   
   module MODULE_VAR_EXPORT config_log_module;
   
  @@ -176,6 +177,21 @@
   static mode_t xfer_mode = ( S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH );
   #endif
   
  +/* POSIX.1 defines PIPE_BUF as the maximum number of bytes that is
  + * guaranteed to be atomic when writing a pipe.  And PIPE_BUF >= 512
  + * is guaranteed.  So we'll just guess 512 in the event the system
  + * doesn't have this.  Now, for file writes there is actually no limit,
  + * the entire write is atomic.  Whether all systems implement this
  + * correctly is another question entirely ... so we'll just use PIPE_BUF
  + * because it's probably a good guess as to what is implemented correctly
  + * everywhere.
  + */
  +#ifdef PIPE_BUF
  +#define LOG_BUFSIZE  PIPE_BUF
  +#else
  +#define LOG_BUFSIZE  (512)
  +#endif
  +
   /*
    * multi_log_state is our per-(virtual)-server configuration. We store
    * an array of the logs we are going to use, each of type config_log_state.
  @@ -211,6 +227,10 @@
       char *fname;
       array_header *format;
       int log_fd;
  +#ifdef BUFFERED_LOGS
  +    int outcnt;
  +    char outbuf[LOG_BUFSIZE];
  +#endif
   } config_log_state;
   
   /*
  @@ -527,6 +547,16 @@
       return cp ? cp : "-";
   }
   
  +#ifdef BUFFERED_LOGS
  +static void flush_log (config_log_state *cls)
  +{
  +    if (cls->outcnt && cls->log_fd != -1) {
  +     write (cls->log_fd, cls->outbuf, cls->outcnt);
  +     cls->outcnt = 0;
  +    }
  +}
  +#endif
  +
   static int config_log_transaction(request_rec *r, config_log_state *cls,
                           array_header *default_format) {
       array_header *strsa;
  @@ -564,8 +594,20 @@
           strcpy (s, strs[i]);
           s += strlen (strs[i]);
       }
  -    
  -    write(cls->log_fd, str, strlen(str));
  +
  +#ifdef BUFFERED_LOGS
  +    if (len + cls->outcnt > LOG_BUFSIZE) {
  +     flush_log (cls);
  +    }
  +    if (len >= LOG_BUFSIZE) {
  +     write (cls->log_fd, str, len);
  +    } else {
  +     memcpy (&cls->outbuf[cls->outcnt], str, len);
  +     cls->outcnt += len;
  +    }
  +#else
  +    write (cls->log_fd, str, len);
  +#endif
   
       return OK;
   }
  @@ -608,7 +650,7 @@
        (multi_log_state *)palloc(p, sizeof (multi_log_state));
       
       mls->config_logs = 
  -     make_array(p, 5, sizeof (config_log_state));
  +     make_array(p, 1, sizeof (config_log_state));
       mls->default_format = NULL;
       mls->server_config_logs = NULL;
       mls->formats = make_table(p, 4);
  @@ -745,6 +787,9 @@
               exit(1);
           }
       }
  +#ifdef BUFFERED_LOGS
  +    cls->outcnt = 0;
  +#endif
   
       return cls;
   }
  @@ -793,6 +838,32 @@
       for (s = s->next; s; s = s->next) open_multi_logs (s, p);
   }
   
  +#ifdef BUFFERED_LOGS
  +static void flush_all_logs (server_rec *s, pool *p)
  +{
  +    multi_log_state *mls;
  +    array_header *log_list;
  +    config_log_state *clsarray;
  +    int i;
  +    
  +    for (; s; s = s->next) {
  +     mls = get_module_config(s->module_config, &config_log_module);
  +     log_list = NULL;
  +     if (mls->config_logs->nelts) {
  +         log_list = mls->config_logs;
  +     } else if (mls->server_config_logs) {
  +         log_list = mls->server_config_logs;
  +     }
  +     if (log_list) {
  +         clsarray = (config_log_state *)log_list->elts;
  +         for (i = 0; i < log_list->nelts; ++i) {
  +             flush_log (&clsarray[i]);
  +         }
  +     }
  +    }
  +}
  +#endif
  +
   module MODULE_VAR_EXPORT config_log_module = {
      STANDARD_MODULE_STUFF,
      init_config_log,          /* initializer */
  @@ -811,6 +882,10 @@
      multi_log_transaction,    /* logger */
      NULL,                     /* header parser */
      NULL,                     /* child_init */
  -   NULL,                     /* child_exit */
  +#ifdef BUFFERED_LOGS
  +   flush_all_logs,           /* child_exit */
  +#else
  +   NULL,
  +#endif
      NULL                              /* post read-request */
   };
  
  
  
  1.63      +20 -8     apachen/src/modules/standard/mod_status.c
  
  Index: mod_status.c
  ===================================================================
  RCS file: /export/home/cvs/apachen/src/modules/standard/mod_status.c,v
  retrieving revision 1.62
  retrieving revision 1.63
  diff -u -r1.62 -r1.63
  --- mod_status.c      1997/09/11 19:32:49     1.62
  +++ mod_status.c      1997/09/12 20:37:38     1.63
  @@ -126,6 +126,7 @@
   
   module MODULE_VAR_EXPORT status_module;
   
  +#ifdef STATUS
   /* Format the number of bytes nicely */
   
   static void format_byte_out(request_rec *r,unsigned long bytes)
  @@ -149,6 +150,7 @@
       else
        rprintf(r,"%.1f GB",(float)kbytes/MBYTE);
   }
  +#endif
   
   static void show_time(request_rec *r,time_t tsecs)
   {
  @@ -223,7 +225,8 @@
       int no_table_report=0;
       server_rec *server = r->server;
       short_score score_record;
  -    char status[]="??????????";
  +    parent_score ps_record;
  +    char status[SERVER_NUM_STATUS];
       char stat_buffer[HARD_SERVER_LIMIT];
       clock_t tu,ts,tcu,tcs;
   
  @@ -290,9 +293,10 @@
       sync_scoreboard_image();
       for (i = 0; i<HARD_SERVER_LIMIT; ++i)
       {
  -        score_record = get_scoreboard_info(i);
  +     score_record = scoreboard_image->servers[i];
  +     ps_record = scoreboard_image->parent[i];
           res = score_record.status;
  -     stat_buffer[i] = status[res];
  +     stat_buffer[i] = (res == SERVER_UNKNOWN) ? '?' : status[res];
           if (res == SERVER_READY)
            ready++;
           else if (res != SERVER_DEAD && res != SERVER_UNKNOWN)
  @@ -300,8 +304,7 @@
   #if defined(STATUS)
           lres = score_record.access_count;
        bytes= score_record.bytes_served;
  -        if (lres!=0 || (score_record.status != SERVER_READY
  -       && score_record.status != SERVER_DEAD))
  +        if (lres!=0 || (res != SERVER_READY && res != SERVER_DEAD))
        {
   #ifndef NO_TIMES
            tu+=score_record.times.tms_utime;
  @@ -444,7 +447,8 @@
   
       for (i = 0; i<HARD_SERVER_LIMIT; ++i)
       {
  -        score_record=get_scoreboard_info(i);
  +     score_record = scoreboard_image->servers[i];
  +     ps_record = scoreboard_image->parent[i];
   
   #if defined(NO_GETTIMEOFDAY)
   #ifndef NO_TIMES
  @@ -487,7 +491,7 @@
                         i,(int)conn_lres,my_lres,lres);
                    else
                        rprintf(r,"<b>Server %d</b> (%d): %d|%lu|%lu [",
  -                      i,(int)score_record.x.pid,(int)conn_lres,my_lres,lres);
  +                      i,(int)ps_record.pid,(int)conn_lres,my_lres,lres);
   
                    switch (score_record.status)
                    {
  @@ -533,7 +537,11 @@
                            score_record.times.tms_cutime/tick,
                            score_record.times.tms_cstime/tick,
   #endif
  +#ifdef OPTIMIZE_TIMEOUTS
  +                         difftime(nowtime, ps_record.last_rtime),
  +#else
                            difftime(nowtime, score_record.last_used),
  +#endif
                            (long)req_time);
                    format_byte_out(r,conn_bytes);
                    rputs("|",r);
  @@ -552,7 +560,7 @@
                         i,(int)conn_lres,my_lres,lres);
                    else
                        rprintf(r,"<tr><td><b>%d</b><td>%d<td>%d/%lu/%lu",
  -                      i,(int)score_record.x.pid,(int)conn_lres,my_lres,lres);
  +                      i,(int)ps_record.pid,(int)conn_lres,my_lres,lres);
   
                    switch (score_record.status)
                    {
  @@ -597,7 +605,11 @@
                            score_record.times.tms_cutime +
                            score_record.times.tms_cstime)/tick,
   #endif
  +#ifdef OPTIMIZE_TIMEOUTS
  +                         difftime(nowtime, ps_record.last_rtime),
  +#else
                            difftime(nowtime, score_record.last_used),
  +#endif
                            (long)req_time);
                    rprintf(r,"<td>%-1.1f<td>%-2.2f<td>%-2.2f\n",
                        (float)conn_bytes/KBYTE, (float)my_bytes/MBYTE,
  
  
  

Reply via email to