]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MAJOR] replaced all timeouts with struct timeval
authorWilly Tarreau <w@1wt.eu>
Sat, 12 May 2007 20:35:00 +0000 (22:35 +0200)
committerWilly Tarreau <w@1wt.eu>
Sat, 12 May 2007 20:35:00 +0000 (22:35 +0200)
The timeout functions were difficult to manipulate because they were
rounding results to the millisecond. Thus, it was difficult to compare
and to check what expired and what did not. Also, the comparison
functions were heavy with multiplies and divides by 1000. Now, all
timeouts are stored in timevals, reducing the number of operations
for updates and leading to cleaner and more efficient code.

26 files changed:
include/common/appsession.h
include/proto/checks.h
include/proto/proto_http.h
include/proto/proxy.h
include/proto/queue.h
include/proto/task.h
include/types/buffers.h
include/types/fd.h
include/types/proxy.h
include/types/task.h
src/appsession.c
src/backend.c
src/cfgparse.c
src/checks.c
src/client.c
src/ev_epoll.c
src/ev_poll.c
src/ev_select.c
src/ev_sepoll.c
src/haproxy.c
src/proto_http.c
src/proxy.c
src/queue.c
src/stream_sock.c
src/task.c
src/time.c

index eb9ba2d0ff3c25cc2f59bb11b6ca962f3b61d997..8fa681cae1031ff46dcf89ea853fa85045106d61 100644 (file)
@@ -44,7 +44,7 @@ void destroy(void *data);
 static void print_table(const CHTbl *htbl);
 #endif
 
-int appsession_refresh(struct task *t);
+void appsession_refresh(struct task *t, struct timeval *next);
 int appsession_task_init(void);
 int appsession_init(void);
 void appsession_cleanup(void);
index 6ac32a1c9c2dd76818ee75bd14c787029153f78a..839af55a53c69b3ef3103800bf25199512d4492a 100644 (file)
@@ -2,7 +2,7 @@
   include/proto/checks.h
   Functions prototypes for the checks.
 
-  Copyright (C) 2000-2006 Willy Tarreau - w@1wt.eu
+  Copyright (C) 2000-2007 Willy Tarreau - w@1wt.eu
   
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
@@ -25,7 +25,7 @@
 #include <types/task.h>
 #include <common/config.h>
 
-int process_chk(struct task *t);
+void process_chk(struct task *t, struct timeval *next);
 
 #endif /* _PROTO_CHECKS_H */
 
index 298d30d074acec514fc074cd605f9869d0c0b33d..da4ea0e94e7d9a821cfc49dbcc96760f574d54ec 100644 (file)
@@ -58,7 +58,7 @@ extern const char http_is_ver_token[256];
 #define HTTP_IS_VER_TOKEN(x) (http_is_ver_token[(unsigned char)(x)])
 
 int event_accept(int fd);
-int process_session(struct task *t);
+void process_session(struct task *t, struct timeval *next);
 int process_cli(struct session *t);
 int process_srv(struct session *t);
 
index 3fa541a2db3a4acd26a7864f20c5046376329910..38d7325cc36db602ed9cc824812da1ec5e686b6d 100644 (file)
@@ -2,7 +2,7 @@
   include/proto/proxy.h
   This file defines function prototypes for proxy management.
 
-  Copyright (C) 2000-2006 Willy Tarreau - w@1wt.eu
+  Copyright (C) 2000-2007 Willy Tarreau - w@1wt.eu
   
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
 #define _PROTO_PROXY_H
 
 #include <common/config.h>
+#include <common/time.h>
 #include <types/proxy.h>
 
 int start_proxies(int verbose);
-int maintain_proxies(void);
+void maintain_proxies(struct timeval *next);
 void soft_stop(void);
 void pause_proxy(struct proxy *p);
 void pause_proxies(void);
index c113f0352f5dbdddb034c0f71c65297b3a496fb7..4370cb39d8d018d2a9dd9ac511a27b10479b2419 100644 (file)
@@ -2,7 +2,7 @@
   include/proto/queue.h
   This file defines everything related to queues.
 
-  Copyright (C) 2000-2006 Willy Tarreau - w@1wt.eu
+  Copyright (C) 2000-2007 Willy Tarreau - w@1wt.eu
   
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
@@ -35,7 +35,7 @@
 struct session *pendconn_get_next_sess(struct server *srv, struct proxy *px);
 struct pendconn *pendconn_add(struct session *sess);
 void pendconn_free(struct pendconn *p);
-int process_srv_queue(struct task *t);
+void process_srv_queue(struct task *t, struct timeval *next);
 unsigned int srv_dynamic_maxconn(const struct server *s);
 
 
index 2c724ad61facaff1b6188487ac749005f7385c0a..c594d525ed5fc485b1e32381a3da985a1258bd29 100644 (file)
@@ -111,12 +111,10 @@ struct task *task_queue(struct task *task);
  *   - wake up all expired tasks
  *   - call all runnable tasks
  *   - call maintain_proxies() to enable/disable the listeners
- *   - return the delay till next event in ms, -1 = wait indefinitely
- * Note: this part should be rewritten with the O(ln(n)) scheduler.
- *
+ *   - return the date of next event in <next> or eternity.
  */
 
-int process_runnable_tasks();
+void process_runnable_tasks(struct timeval *next);
 
 
 #endif /* _PROTO_TASK_H */
index 4afc293e3c6c828304cac77ddac3a829d30220a8..9b781b8421a6a69965e3fc3d6c6d27f816341391 100644 (file)
@@ -63,9 +63,9 @@ struct buffer {
        struct timeval rex;             /* expiration date for a read  */
        struct timeval wex;             /* expiration date for a write */
        struct timeval cex;             /* expiration date for a connect */
-       int rto;                        /* read timeout */
-       int wto;                        /* write timeout */
-       int cto;                        /* connect timeout */
+       struct timeval rto;             /* read timeout */
+       struct timeval wto;             /* write timeout */
+       struct timeval cto;             /* connect timeout */
        unsigned int l;                 /* data length */
        char *r, *w, *lr;               /* read ptr, write ptr, last read */
        char *rlim;                     /* read limit, used for header rewriting */
index 392c94ee7462ab7a97e0d530a8949dfd905900a7..a1b6e9d4d4859108d0270bad6232de52817a05e7 100644 (file)
@@ -81,7 +81,7 @@ struct fdtab {
  *    it returns 0. It may be the same as clr().
  *  - clo() should be used to do indicate the poller that fd will be closed. It
  *    may be the same as rem() on some pollers.
- *  - poll() calls the poller, waiting at most wait_time ms.
+ *  - poll() calls the poller, expiring at <exp>
  */
 struct poller {
        void   *private;                                     /* any private data for the poller */
@@ -92,7 +92,7 @@ struct poller {
        int  REGPRM2 (*cond_c)(const int fd, int dir);       /* clear polling on <fd> for <dir> if set */
        void REGPRM1    (*rem)(const int fd);                /* remove any polling on <fd> */
        void REGPRM1    (*clo)(const int fd);                /* mark <fd> as closed */
-       void REGPRM2   (*poll)(struct poller *p, int wait_time); /* the poller itself */
+       void REGPRM2   (*poll)(struct poller *p, struct timeval *exp); /* the poller itself */
        int  REGPRM1   (*init)(struct poller *p);            /* poller initialization */
        void REGPRM1   (*term)(struct poller *p);            /* termination of this poller */
        int  REGPRM1   (*test)(struct poller *p);            /* pre-init check of the poller */
index c403e59f4c0591b74da293337d7f7ce5825bbddb..532348ec9a36ced1169db09773bcd21dcc2a66f1 100644 (file)
@@ -96,7 +96,6 @@ struct proxy {
        char *appsession_name;                  /* name of the cookie to look for */
        int  appsession_name_len;               /* strlen(appsession_name), computed only once */
        int  appsession_len;                    /* length of the appsession cookie value to be used */
-       int  appsession_timeout;
        CHTbl htbl_proxy;                       /* Per Proxy hashtable */
        char *capture_name;                     /* beginning of the name of the cookie to capture */
        int  capture_namelen;                   /* length of the cookie name to match */
@@ -104,9 +103,10 @@ struct proxy {
        struct uri_auth *uri_auth;              /* if non-NULL, the (list of) per-URI authentications */
        char *monitor_uri;                      /* a special URI to which we respond with HTTP/200 OK */
        int monitor_uri_len;                    /* length of the string above. 0 if unused */
-       int clitimeout;                         /* client I/O timeout (in milliseconds) */
-       int srvtimeout;                         /* server I/O timeout (in milliseconds) */
-       int contimeout;                         /* connect timeout (in milliseconds) */
+       struct timeval clitimeout;              /* client I/O timeout (in milliseconds) */
+       struct timeval srvtimeout;              /* server I/O timeout (in milliseconds) */
+       struct timeval contimeout;              /* connect timeout (in milliseconds) */
+       struct timeval appsession_timeout;
        char *id;                               /* proxy id */
        struct list pendconns;                  /* pending connections with no server assigned yet */
        int nbpend, nbpend_max;                 /* number of pending connections with no server assigned yet */
index 1fd78be56bb99e8582478ef18318e27359776b4a..42699dbfff886f305421f336dd3b22a21dbc78ad 100644 (file)
@@ -2,7 +2,7 @@
   include/types/task.h
   Macros, variables and structures for task management.
 
-  Copyright (C) 2000-2006 Willy Tarreau - w@1wt.eu
+  Copyright (C) 2000-2007 Willy Tarreau - w@1wt.eu
   
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
@@ -38,7 +38,7 @@ struct task {
        struct ultree *wq;              /* NULL if unqueued, or back ref to the carrier node in the WQ */
        int state;                      /* task state : IDLE or RUNNING */
        struct timeval expire;          /* next expiration time for this task, use only for fast sorting */
-       int (*process)(struct task *t); /* the function which processes the task */
+       void (*process)(struct task *t, struct timeval *next);  /* the function which processes the task */
        void *context;                  /* the task's context */
 };
 
index d11fb195072b078da47f01dc75f9b396a2c333c3..0307ff7c4a8e857e71ac2c1b308da7f156f18f7e 100644 (file)
@@ -125,7 +125,7 @@ int appsession_task_init(void)
        return 0;
 }
 
-int appsession_refresh(struct task *t)
+void appsession_refresh(struct task *t, struct timeval *next)
 {
        struct proxy       *p = proxy;
        CHTbl              *htbl;
@@ -143,7 +143,7 @@ int appsession_refresh(struct task *t)
                                for (element = list_head(&htbl->table[i]);
                                     element != NULL; element = list_next(element)) {
                                        asession = (appsess *)list_data(element);
-                                       if (tv_ms_le2(&asession->expire, &now)) {
+                                       if (__tv_isle(&asession->expire, &now)) {
                                                if ((global.mode & MODE_DEBUG) &&
                                                    (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))) {
                                                        int len;
@@ -165,7 +165,7 @@ int appsession_refresh(struct task *t)
                                                }
                                                else
                                                        element = last;
-                                       }/* end if (tv_ms_le2(&asession->expire, &now)) */
+                                       }/* end if (__tv_isle(&asession->expire, &now)) */
                                        else
                                                last = element;
                                }/* end  for (element = list_head(&htbl->table[i]); element != NULL; element = list_next(element)) */
@@ -174,7 +174,7 @@ int appsession_refresh(struct task *t)
                p = p->next;
        }
        tv_ms_add(&t->expire, &now, TBLCHKINT); /* check expiration every 5 seconds */
-       return TBLCHKINT;
+       *next = t->expire;
 } /* end appsession_refresh */
 
 int match_str(const void *key1, const void *key2)
index 69e79d408d7745bd441c3407752c615f5634529c..002394ea4c59b37a9289a3f8108319048987235a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Backend variables and functions.
  *
- * Copyright 2000-2006 Willy Tarreau <w@1wt.eu>
+ * Copyright 2000-2007 Willy Tarreau <w@1wt.eu>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -550,8 +550,8 @@ int connect_server(struct session *s)
                        s->srv->cur_sess_max = s->srv->cur_sess;
        }
 
-       if (s->be->contimeout)
-               tv_ms_add(&s->req->cex, &now, s->be->contimeout);
+       if (tv_isset(&s->be->contimeout))
+               tv_add(&s->req->cex, &now, &s->be->contimeout);
        else
                tv_eternity(&s->req->cex);
        return SN_ERR_NONE;  /* connection is OK */
@@ -680,8 +680,8 @@ int srv_redispatch_connect(struct session *t)
 
        case SRV_STATUS_QUEUED:
                /* FIXME-20060503 : we should use the queue timeout instead */
-               if (t->be->contimeout)
-                       tv_ms_add(&t->req->cex, &now, t->be->contimeout);
+               if (tv_isset(&t->be->contimeout))
+                       tv_add(&t->req->cex, &now, &t->be->contimeout);
                else
                        tv_eternity(&t->req->cex);
                t->srv_state = SV_STIDLE;
index b2e76b310f783e4582687083aa1021428c3b47e5..1edaa8fc0b52068df8eb67e8c39bb7c185c47151 100644 (file)
@@ -766,7 +766,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args)
                curproxy->appsession_name = strdup(args[1]);
                curproxy->appsession_name_len = strlen(curproxy->appsession_name);
                curproxy->appsession_len = atoi(args[3]);
-               curproxy->appsession_timeout = atoi(args[5]);
+               __tv_from_ms(&curproxy->appsession_timeout, atoi(args[5]));
                rc = chtbl_init(&(curproxy->htbl_proxy), TBLSIZ, hashpjw, match_str, destroy);
                if (rc) {
                        Alert("Error Init Appsession Hashtable.\n");
@@ -857,7 +857,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args)
                }
        }
        else if (!strcmp(args[0], "contimeout")) {  /* connect timeout */
-               if (curproxy->contimeout != defproxy.contimeout) {
+               if (!__tv_iseq(&curproxy->contimeout, &defproxy.contimeout)) {
                        Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
                        return 0;
                }
@@ -869,10 +869,10 @@ int cfg_parse_listen(const char *file, int linenum, char **args)
                              file, linenum, args[0]);
                        return -1;
                }
-               curproxy->contimeout = atol(args[1]);
+               __tv_from_ms(&curproxy->contimeout, atol(args[1]));
        }
        else if (!strcmp(args[0], "clitimeout")) {  /*  client timeout */
-               if (curproxy->clitimeout != defproxy.clitimeout) {
+               if (!__tv_iseq(&curproxy->clitimeout, &defproxy.clitimeout)) {
                        Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
                              file, linenum, args[0]);
                        return 0;
@@ -885,10 +885,10 @@ int cfg_parse_listen(const char *file, int linenum, char **args)
                              file, linenum, args[0]);
                        return -1;
                }
-               curproxy->clitimeout = atol(args[1]);
+               __tv_from_ms(&curproxy->clitimeout, atol(args[1]));
        }
        else if (!strcmp(args[0], "srvtimeout")) {  /*  server timeout */
-               if (curproxy->srvtimeout != defproxy.srvtimeout) {
+               if (!__tv_iseq(&curproxy->srvtimeout, &defproxy.srvtimeout)) {
                        Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
                        return 0;
                }
@@ -900,7 +900,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args)
                              file, linenum, args[0]);
                        return -1;
                }
-               curproxy->srvtimeout = atol(args[1]);
+               __tv_from_ms(&curproxy->srvtimeout, atol(args[1]));
        }
        else if (!strcmp(args[0], "retries")) {  /* connection retries */
                if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
@@ -2385,8 +2385,9 @@ int readcfgfile(const char *file)
                        }
                }
                if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
-                   (((curproxy->cap & PR_CAP_FE) && !curproxy->clitimeout) ||
-                    ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) && (!curproxy->contimeout || !curproxy->srvtimeout)))) {
+                   (((curproxy->cap & PR_CAP_FE) && !tv_isset(&curproxy->clitimeout)) ||
+                    ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
+                     (!tv_isset(&curproxy->contimeout) || !tv_isset(&curproxy->srvtimeout))))) {
                        Warning("parsing %s : missing timeouts for %s '%s'.\n"
                                "   | While not properly invalid, you will certainly encounter various problems\n"
                                "   | with such a configuration. To fix this, please ensure that all following\n"
index 83a539eea1b02c4c875e15545ea5e4316ae01fb8..96f5895f6cfd8f585da811ad3882632adf200e04 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Health-checks functions.
  *
- * Copyright 2000-2006 Willy Tarreau <w@1wt.eu>
+ * Copyright 2000-2007 Willy Tarreau <w@1wt.eu>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -275,13 +275,12 @@ static int event_srv_chk_r(int fd)
  * manages a server health-check. Returns
  * the time the task accepts to wait, or TIME_ETERNITY for infinity.
  */
-int process_chk(struct task *t)
+void process_chk(struct task *t, struct timeval *next)
 {
        __label__ new_chk, out;
        struct server *s = t->context;
        struct sockaddr_in sa;
        int fd;
-       int next_time;
 
        //fprintf(stderr, "process_chk: task=%p\n", t);
 
@@ -289,9 +288,9 @@ int process_chk(struct task *t)
        fd = s->curfd;
        if (fd < 0) {   /* no check currently running */
                //fprintf(stderr, "process_chk: 2\n");
-               if (!tv_ms_le2(&t->expire, &now)) { /* not good time yet */
+               if (!__tv_isle(&t->expire, &now)) { /* not good time yet */
                        task_queue(t);  /* restore t to its place in the task list */
-                       next_time = tv_ms_remain2(&now, &t->expire);
+                       *next = t->expire;
                        goto out;
                }
 
@@ -299,10 +298,10 @@ int process_chk(struct task *t)
                 * the server should not be checked.
                 */
                if (!(s->state & SRV_CHECKED) || s->proxy->state == PR_STSTOPPED) {
-                       while (tv_ms_le2(&t->expire, &now))
+                       while (__tv_isle(&t->expire, &now))
                                tv_ms_add(&t->expire, &t->expire, s->inter);
                        task_queue(t);  /* restore t to its place in the task list */
-                       next_time = tv_ms_remain2(&now, &t->expire);
+                       *next = t->expire;
                        goto out;
                }
 
@@ -410,7 +409,7 @@ int process_chk(struct task *t)
                                                /* FIXME: we allow up to <inter> for a connection to establish, but we should use another parameter */
                                                tv_ms_add(&t->expire, &now, s->inter);
                                                task_queue(t);  /* restore t to its place in the task list */
-                                               return tv_ms_remain(&now, &t->expire);
+                                               *next = t->expire;
                                        }
                                        else if (errno != EALREADY && errno != EISCONN && errno != EAGAIN) {
                                                s->result = -1;    /* a real error */
@@ -422,7 +421,7 @@ int process_chk(struct task *t)
 
                if (!s->result) { /* nothing done */
                        //fprintf(stderr, "process_chk: 6\n");
-                       while (tv_ms_le2(&t->expire, &now))
+                       while (__tv_isle(&t->expire, &now))
                                tv_ms_add(&t->expire, &t->expire, s->inter);
                        goto new_chk; /* may be we should initialize a new check */
                }
@@ -437,7 +436,7 @@ int process_chk(struct task *t)
 
                //fprintf(stderr, "process_chk: 7\n");
                /* FIXME: we allow up to <inter> for a connection to establish, but we should use another parameter */
-               while (tv_ms_le2(&t->expire, &now))
+               while (__tv_isle(&t->expire, &now))
                        tv_ms_add(&t->expire, &t->expire, s->inter);
                goto new_chk;
        }
@@ -488,11 +487,11 @@ int process_chk(struct task *t)
                        }
                        s->curfd = -1; /* no check running anymore */
                        fd_delete(fd);
-                       while (tv_ms_le2(&t->expire, &now))
+                       while (__tv_isle(&t->expire, &now))
                                tv_ms_add(&t->expire, &t->expire, s->inter);
                        goto new_chk;
                }
-               else if (s->result < 0 || tv_ms_le2(&t->expire, &now)) {
+               else if (s->result < 0 || __tv_isle(&t->expire, &now)) {
                        //fprintf(stderr, "process_chk: 10\n");
                        /* failure or timeout detected */
                        if (s->health > s->rise) {
@@ -503,7 +502,7 @@ int process_chk(struct task *t)
                                set_server_down(s);
                        s->curfd = -1;
                        fd_delete(fd);
-                       while (tv_ms_le2(&t->expire, &now))
+                       while (__tv_isle(&t->expire, &now))
                                tv_ms_add(&t->expire, &t->expire, s->inter);
                        goto new_chk;
                }
@@ -512,12 +511,9 @@ int process_chk(struct task *t)
        //fprintf(stderr, "process_chk: 11\n");
        s->result = 0;
        task_queue(t);  /* restore t to its place in the task list */
-       next_time = tv_ms_remain2(&now, &t->expire);
+       *next = t->expire;
  out:
-       /* Ensure that we don't report sub-millisecond timeouts */
-       if (next_time != TIME_ETERNITY)
-               next_time++;
-       return next_time;
+       return;
 }
 
 
index 4a891b06d126e7ea57cbfa20211977478cd4a6ea..52b281bded81100cf177ad0523957b6cfc6d956a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Client-side variables and functions.
  *
- * Copyright 2000-2006 Willy Tarreau <w@1wt.eu>
+ * Copyright 2000-2007 Willy Tarreau <w@1wt.eu>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -386,7 +386,7 @@ int event_accept(int fd) {
 
                s->rep->rto = s->be->srvtimeout;
                s->rep->wto = s->fe->clitimeout;
-               s->rep->cto = 0;
+               tv_zero(&s->rep->cto);
 
                fd_insert(cfd);
                fdtab[cfd].owner = t;
@@ -421,13 +421,13 @@ int event_accept(int fd) {
                tv_eternity(&s->rep->wex);
                tv_eternity(&t->expire);
 
-               if (s->fe->clitimeout) {
+               if (tv_isset(&s->fe->clitimeout)) {
                        if (EV_FD_ISSET(cfd, DIR_RD)) {
-                               tv_ms_add(&s->req->rex, &now, s->fe->clitimeout);
+                               tv_add(&s->req->rex, &now, &s->fe->clitimeout);
                                t->expire = s->req->rex;
                        }
                        if (EV_FD_ISSET(cfd, DIR_WR)) {
-                               tv_ms_add(&s->rep->wex, &now, s->fe->clitimeout);
+                               tv_add(&s->rep->wex, &now, &s->fe->clitimeout);
                                t->expire = s->req->rex;
                        }
                }
index b4844998ad495bd549821b631bab1cbb0db091e8..a867e8dc369605bc8b3013b6bdbb3a140b0a681d 100644 (file)
@@ -220,16 +220,22 @@ REGPRM1 static void __fd_clo(int fd)
 /*
  * epoll() poller
  */
-REGPRM2 static void _do_poll(struct poller *p, int wait_time)
+REGPRM2 static void _do_poll(struct poller *p, struct timeval *exp)
 {
        int status;
        int fd;
        int count;
+       int wait_time;
 
        if (likely(nbchanges))
                fd_flush_changes();
 
        /* now let's wait for events */
+       if (tv_isset(exp))
+               wait_time = tv_ms_remain(&now, exp);
+       else
+               wait_time = -1;
+
        status = epoll_wait(epoll_fd, epoll_events, maxfd, wait_time);
        tv_now(&now);
 
index c48f502151f87c181eab32347bfc2f6e196bd99c..3c97707cc88fb55bcfb19f7159624b65d438aecf 100644 (file)
@@ -81,10 +81,11 @@ REGPRM1 static void __fd_rem(const int fd)
 /*
  * Poll() poller
  */
-REGPRM2 static void _do_poll(struct poller *p, int wait_time)
+REGPRM2 static void _do_poll(struct poller *p, struct timeval *exp)
 {
        int status;
        int fd, nbfd;
+       int wait_time;
 
        int fds, count;
        int sr, sw;
@@ -123,6 +124,11 @@ REGPRM2 static void _do_poll(struct poller *p, int wait_time)
        }
       
        /* now let's wait for events */
+       if (tv_isset(exp))
+               wait_time = tv_ms_remain(&now, exp);
+       else
+               wait_time = -1;
+
        status = poll(poll_events, nbfd, wait_time);
        tv_now(&now);
 
index ed79abf01e959197fec773acacc42cdd75515081..fb5cc41eab739e2fc21c59395a584bbd5a525c5d 100644 (file)
@@ -78,7 +78,7 @@ REGPRM1 static void __fd_rem(int fd)
 /*
  * Select() poller
  */
-REGPRM2 static void _do_poll(struct poller *p, int wait_time)
+REGPRM2 static void _do_poll(struct poller *p, struct timeval *exp)
 {
        int status;
        int fd, i;
@@ -89,12 +89,14 @@ REGPRM2 static void _do_poll(struct poller *p, int wait_time)
                
        /* allow select to return immediately when needed */
        delta.tv_sec = delta.tv_usec = 0;
-       if (wait_time > 0) {  /* FIXME */
-               /* Convert to timeval */
-               /* to avoid eventual select loops due to timer precision */
-               wait_time += SCHEDULER_RESOLUTION;
-               delta.tv_sec  = wait_time / 1000; 
-               delta.tv_usec = (wait_time % 1000) * 1000;
+       if (tv_isset(exp)) {
+               tv_remain(&now, exp, &delta);
+               /* To avoid eventual select loops due to timer precision */
+               delta.tv_usec += SCHEDULER_RESOLUTION * 1000;
+               if (delta.tv_usec >= 1000000) {
+                       delta.tv_usec -= 1000000;
+                       delta.tv_sec ++;
+               }
        }
 
        /* let's restore fdset state */
@@ -118,7 +120,7 @@ REGPRM2 static void _do_poll(struct poller *p, int wait_time)
                        readnotnull ? tmp_evts[DIR_RD] : NULL,
                        writenotnull ? tmp_evts[DIR_WR] : NULL,
                        NULL,
-                       (wait_time >= 0) ? &delta : NULL);
+                       tv_isset(exp) ? &delta : NULL);
       
        tv_now(&now);
 
index c3b777647e265ce4789152a5ce759a4860166729..d2fcc7c7c26a58771ec61f5b4e988184a1993b42 100644 (file)
@@ -259,13 +259,14 @@ static struct ev_to_epoll {
 /*
  * speculative epoll() poller
  */
-REGPRM2 static void _do_poll(struct poller *p, int wait_time)
+REGPRM2 static void _do_poll(struct poller *p, struct timeval *exp)
 {
        static unsigned int last_skipped;
        int status;
        int fd, opcode;
        int count;
        int spec_idx;
+       int wait_time;
 
 
        /* Here we have two options :
@@ -370,6 +371,12 @@ REGPRM2 static void _do_poll(struct poller *p, int wait_time)
                }
                wait_time = 0;
        }
+       else {
+               if (tv_isset(exp))
+                       wait_time = tv_ms_remain(&now, exp);
+               else
+                       wait_time = -1;
+       }
        last_skipped = 0;
 
        /* now let's wait for events */
index a2e335e1eee4c055b07f02456fbbea0c6a825527..0acf75fb5d7e7b8dc394bf687568bde6bc294031 100644 (file)
@@ -684,17 +684,17 @@ static void tell_old_pids(int sig)
  */
 void run_poll_loop()
 {
-       int next_time;
-       tv_now(&now);
+       struct timeval next;
 
+       tv_now(&now);
        while (1) {
-               next_time = process_runnable_tasks();
+               process_runnable_tasks(&next);
 
                /* stop when there's no connection left and we don't allow them anymore */
                if (!actconn && listeners == 0)
                        break;
 
-               cur_poller.poll(&cur_poller, next_time);
+               cur_poller.poll(&cur_poller, &next);
        }
 }
 
index 9506b167eb98fea897acc281635cd1eb3cbd254f..0f78d07a740e66bb5e265509825ff00fc04df402 100644 (file)
@@ -442,8 +442,8 @@ void client_retnclose(struct session *s, const struct chunk *msg)
        EV_FD_CLR(s->cli_fd, DIR_RD);
        EV_FD_SET(s->cli_fd, DIR_WR);
        tv_eternity(&s->req->rex);
-       if (s->fe->clitimeout)
-               tv_ms_add(&s->rep->wex, &now, s->fe->clitimeout);
+       if (tv_isset(&s->fe->clitimeout))
+               tv_add(&s->rep->wex, &now, &s->fe->clitimeout);
        else
                tv_eternity(&s->rep->wex);
        s->cli_state = CL_STSHUTR;
@@ -532,7 +532,7 @@ static http_meth_t find_http_meth(const char *str, const int len)
  * the time the task accepts to wait, or TIME_ETERNITY for
  * infinity.
  */
-int process_session(struct task *t)
+void process_session(struct task *t, struct timeval *next)
 {
        struct session *s = t->context;
        int fsm_resync = 0;
@@ -563,11 +563,11 @@ int process_session(struct task *t)
                /* DEBUG code : this should never ever happen, otherwise it indicates
                 * that a task still has something to do and will provoke a quick loop.
                 */
-               if (tv_ms_remain2(&now, &t->expire) <= 0)
+               if (tv_remain2(&now, &t->expire) <= 0)
                        exit(100);
 #endif
-
-               return tv_ms_remain2(&now, &t->expire); /* nothing more to do */
+               *next = t->expire;
+               return; /* nothing more to do */
        }
 
        s->fe->feconn--;
@@ -615,7 +615,7 @@ int process_session(struct task *t)
        task_delete(t);
        session_free(s);
        task_free(t);
-       return TIME_ETERNITY; /* rest in peace for eternity */
+       tv_eternity(next);
 }
 
 
@@ -1529,7 +1529,7 @@ int process_cli(struct session *t)
                        }
 
                        /* 3: has the read timeout expired ? */
-                       else if (unlikely(tv_ms_le2(&req->rex, &now))) {
+                       else if (unlikely(__tv_isle(&req->rex, &now))) {
                                /* read timeout : give up with an error message. */
                                txn->status = 408;
                                client_retnclose(t, error_message(t, HTTP_ERR_408));
@@ -1547,8 +1547,8 @@ int process_cli(struct session *t)
                                 * full. We cannot loop here since stream_sock_read will disable it only if
                                 * req->l == rlim-data
                                 */
-                               if (t->fe->clitimeout)
-                                       tv_ms_add(&req->rex, &now, t->fe->clitimeout);
+                               if (tv_isset(&t->fe->clitimeout))
+                                       tv_add(&req->rex, &now, &t->fe->clitimeout);
                                else
                                        tv_eternity(&req->rex);
                        }
@@ -1912,8 +1912,8 @@ int process_cli(struct session *t)
 
                t->logs.t_request = tv_ms_elapsed(&t->logs.tv_accept, &now);
 
-               if (!t->fe->clitimeout ||
-                   (t->srv_state < SV_STDATA && t->be->srvtimeout)) {
+               if (!tv_isset(&t->fe->clitimeout) ||
+                   (t->srv_state < SV_STDATA && tv_isset(&t->be->srvtimeout))) {
                        /* If the client has no timeout, or if the server is not ready yet,
                         * and we know for sure that it can expire, then it's cleaner to
                         * disable the timeout on the client side so that too low values
@@ -1936,8 +1936,10 @@ int process_cli(struct session *t)
                        /* flush the request so that we can drop the connection early
                         * if the client closes first.
                         */
-                       tv_ms_add(&req->cex, &now,
-                                    t->be->contimeout ? t->be->contimeout : 0);
+                       if (tv_isset(&t->be->contimeout))
+                               tv_add(&req->cex, &now, &t->be->contimeout);
+                       else
+                               req->cex = now;
                }
 
                /* OK let's go on with the BODY now */
@@ -1996,14 +1998,14 @@ int process_cli(struct session *t)
                        /* We must ensure that the read part is still alive when switching
                         * to shutw */
                        EV_FD_SET(t->cli_fd, DIR_RD);
-                       if (t->fe->clitimeout)
-                               tv_ms_add(&req->rex, &now, t->fe->clitimeout);
+                       if (tv_isset(&t->fe->clitimeout))
+                               tv_add(&req->rex, &now, &t->fe->clitimeout);
                        t->cli_state = CL_STSHUTW;
                        //fprintf(stderr,"%p:%s(%d), c=%d, s=%d\n", t, __FUNCTION__, __LINE__, t->cli_state, t->cli_state);
                        return 1;
                }
                /* read timeout */
-               else if (tv_ms_le2(&req->rex, &now)) {
+               else if (__tv_isle(&req->rex, &now)) {
                        EV_FD_CLR(t->cli_fd, DIR_RD);
                        tv_eternity(&req->rex);
                        t->cli_state = CL_STSHUTR;
@@ -2020,15 +2022,15 @@ int process_cli(struct session *t)
                        return 1;
                }       
                /* write timeout */
-               else if (tv_ms_le2(&rep->wex, &now)) {
+               else if (__tv_isle(&rep->wex, &now)) {
                        EV_FD_CLR(t->cli_fd, DIR_WR);
                        tv_eternity(&rep->wex);
                        shutdown(t->cli_fd, SHUT_WR);
                        /* We must ensure that the read part is still alive when switching
                         * to shutw */
                        EV_FD_SET(t->cli_fd, DIR_RD);
-                       if (t->fe->clitimeout)
-                               tv_ms_add(&req->rex, &now, t->fe->clitimeout);
+                       if (tv_isset(&t->fe->clitimeout))
+                               tv_add(&req->rex, &now, &t->fe->clitimeout);
 
                        t->cli_state = CL_STSHUTW;
                        if (!(t->flags & SN_ERR_MASK))
@@ -2053,8 +2055,8 @@ int process_cli(struct session *t)
                } else {
                        /* there's still some space in the buffer */
                        if (EV_FD_COND_S(t->cli_fd, DIR_RD)) {
-                               if (!t->fe->clitimeout ||
-                                   (t->srv_state < SV_STDATA && t->be->srvtimeout))
+                               if (!tv_isset(&t->fe->clitimeout) ||
+                                   (t->srv_state < SV_STDATA && tv_isset(&t->be->srvtimeout)))
                                        /* If the client has no timeout, or if the server not ready yet, and we
                                         * know for sure that it can expire, then it's cleaner to disable the
                                         * timeout on the client side so that too low values cannot make the
@@ -2062,7 +2064,7 @@ int process_cli(struct session *t)
                                         */
                                        tv_eternity(&req->rex);
                                else
-                                       tv_ms_add(&req->rex, &now, t->fe->clitimeout);
+                                       tv_add(&req->rex, &now, &t->fe->clitimeout);
                        }
                }
 
@@ -2076,8 +2078,8 @@ int process_cli(struct session *t)
                        /* buffer not empty */
                        if (EV_FD_COND_S(t->cli_fd, DIR_WR)) {
                                /* restart writing */
-                               if (t->fe->clitimeout) {
-                                       tv_ms_add(&rep->wex, &now, t->fe->clitimeout);
+                               if (tv_isset(&t->fe->clitimeout)) {
+                                       tv_add(&rep->wex, &now, &t->fe->clitimeout);
                                        /* FIXME: to prevent the client from expiring read timeouts during writes,
                                         * we refresh it. */
                                        req->rex = rep->wex;
@@ -2112,7 +2114,7 @@ int process_cli(struct session *t)
                        t->cli_state = CL_STCLOSE;
                        return 1;
                }
-               else if (tv_ms_le2(&rep->wex, &now)) {
+               else if (__tv_isle(&rep->wex, &now)) {
                        tv_eternity(&rep->wex);
                        fd_delete(t->cli_fd);
                        t->cli_state = CL_STCLOSE;
@@ -2149,8 +2151,8 @@ int process_cli(struct session *t)
                        /* buffer not empty */
                        if (EV_FD_COND_S(t->cli_fd, DIR_WR)) {
                                /* restart writing */
-                               if (t->fe->clitimeout) {
-                                       tv_ms_add(&rep->wex, &now, t->fe->clitimeout);
+                               if (tv_isset(&t->fe->clitimeout)) {
+                                       tv_add(&rep->wex, &now, &t->fe->clitimeout);
                                        /* FIXME: to prevent the client from expiring read timeouts during writes,
                                         * we refresh it. */
                                        req->rex = rep->wex;
@@ -2184,7 +2186,7 @@ int process_cli(struct session *t)
                        t->cli_state = CL_STCLOSE;
                        return 1;
                }
-               else if (tv_ms_le2(&req->rex, &now)) {
+               else if (__tv_isle(&req->rex, &now)) {
                        tv_eternity(&req->rex);
                        fd_delete(t->cli_fd);
                        t->cli_state = CL_STCLOSE;
@@ -2215,8 +2217,8 @@ int process_cli(struct session *t)
                } else {
                        /* there's still some space in the buffer */
                        if (EV_FD_COND_S(t->cli_fd, DIR_RD)) {
-                               if (t->fe->clitimeout)
-                                       tv_ms_add(&req->rex, &now, t->fe->clitimeout);
+                               if (tv_isset(&t->fe->clitimeout))
+                                       tv_add(&req->rex, &now, &t->fe->clitimeout);
                                else
                                        tv_eternity(&req->rex);
                                //fprintf(stderr,"%p:%s(%d), c=%d, s=%d\n", t, __FUNCTION__, __LINE__, t->cli_state, t->cli_state);
@@ -2281,7 +2283,7 @@ int process_srv(struct session *t)
                                 * already set the connect expiration date to the right
                                 * timeout. We just have to check that it has not expired.
                                 */
-                               if (!tv_ms_le2(&req->cex, &now))
+                               if (!__tv_isle(&req->cex, &now))
                                        return 0;
 
                                /* We will set the queue timer to the time spent, just for
@@ -2303,7 +2305,7 @@ int process_srv(struct session *t)
                         * to any other session to release it and wake us up again.
                         */
                        if (t->pend_pos) {
-                               if (!tv_ms_le2(&req->cex, &now))
+                               if (!__tv_isle(&req->cex, &now))
                                        return 0;
                                else {
                                        /* we've been waiting too long here */
@@ -2349,7 +2351,7 @@ int process_srv(struct session *t)
                        srv_close_with_err(t, SN_ERR_CLICL, SN_FINST_C, 0, NULL);
                        return 1;
                }
-               if (!(req->flags & BF_WRITE_STATUS) && !tv_ms_le2(&req->cex, &now)) {
+               if (!(req->flags & BF_WRITE_STATUS) && !__tv_isle(&req->cex, &now)) {
                        //fprintf(stderr,"1: c=%d, s=%d, now=%d.%06d, exp=%d.%06d\n", c, s, now.tv_sec, now.tv_usec, req->cex.tv_sec, req->cex.tv_usec);
                        return 0; /* nothing changed */
                }
@@ -2416,8 +2418,8 @@ int process_srv(struct session *t)
                                tv_eternity(&req->wex);
                        } else  /* need the right to write */ {
                                EV_FD_SET(t->srv_fd, DIR_WR);
-                               if (t->be->srvtimeout) {
-                                       tv_ms_add(&req->wex, &now, t->be->srvtimeout);
+                               if (tv_isset(&t->be->srvtimeout)) {
+                                       tv_add(&req->wex, &now, &t->be->srvtimeout);
                                        /* FIXME: to prevent the server from expiring read timeouts during writes,
                                         * we refresh it. */
                                        rep->rex = req->wex;
@@ -2428,8 +2430,8 @@ int process_srv(struct session *t)
 
                        if (t->be->mode == PR_MODE_TCP) { /* let's allow immediate data connection in this case */
                                EV_FD_SET(t->srv_fd, DIR_RD);
-                               if (t->be->srvtimeout)
-                                       tv_ms_add(&rep->rex, &now, t->be->srvtimeout);
+                               if (tv_isset(&t->be->srvtimeout))
+                                       tv_add(&rep->rex, &now, &t->be->srvtimeout);
                                else
                                        tv_eternity(&rep->rex);
                
@@ -2517,8 +2519,8 @@ int process_srv(struct session *t)
                         * full. We cannot loop here since stream_sock_read will disable it only if
                         * rep->l == rlim-data
                         */
-                       if (t->be->srvtimeout)
-                               tv_ms_add(&rep->rex, &now, t->be->srvtimeout);
+                       if (tv_isset(&t->be->srvtimeout))
+                               tv_add(&rep->rex, &now, &t->be->srvtimeout);
                        else
                                tv_eternity(&rep->rex);
                }
@@ -2584,7 +2586,7 @@ int process_srv(struct session *t)
                        /* read timeout : return a 504 to the client.
                         */
                        else if (unlikely(EV_FD_ISSET(t->srv_fd, DIR_RD) &&
-                                         tv_ms_le2(&rep->rex, &now))) {
+                                         __tv_isle(&rep->rex, &now))) {
                                tv_eternity(&rep->rex);
                                tv_eternity(&req->wex);
                                fd_delete(t->srv_fd);
@@ -2624,8 +2626,8 @@ int process_srv(struct session *t)
                                /* We must ensure that the read part is still
                                 * alive when switching to shutw */
                                EV_FD_SET(t->srv_fd, DIR_RD);
-                               if (t->be->srvtimeout)
-                                       tv_ms_add(&rep->rex, &now, t->be->srvtimeout);
+                               if (tv_isset(&t->be->srvtimeout))
+                                       tv_add(&rep->rex, &now, &t->be->srvtimeout);
 
                                shutdown(t->srv_fd, SHUT_WR);
                                t->srv_state = SV_STSHUTW;
@@ -2638,15 +2640,15 @@ int process_srv(struct session *t)
                         * some work to do on the headers.
                         */
                        else if (unlikely(EV_FD_ISSET(t->srv_fd, DIR_WR) &&
-                                         tv_ms_le2(&req->wex, &now))) {
+                                         __tv_isle(&req->wex, &now))) {
                                EV_FD_CLR(t->srv_fd, DIR_WR);
                                tv_eternity(&req->wex);
                                shutdown(t->srv_fd, SHUT_WR);
                                /* We must ensure that the read part is still alive
                                 * when switching to shutw */
                                EV_FD_SET(t->srv_fd, DIR_RD);
-                               if (t->be->srvtimeout)
-                                       tv_ms_add(&rep->rex, &now, t->be->srvtimeout);
+                               if (tv_isset(&t->be->srvtimeout))
+                                       tv_add(&rep->rex, &now, &t->be->srvtimeout);
 
                                t->srv_state = SV_STSHUTW;
                                if (!(t->flags & SN_ERR_MASK))
@@ -2667,8 +2669,8 @@ int process_srv(struct session *t)
                        else if (likely(req->l)) {
                                if (EV_FD_COND_S(t->srv_fd, DIR_WR)) {
                                        /* restart writing */
-                                       if (t->be->srvtimeout) {
-                                               tv_ms_add(&req->wex, &now, t->be->srvtimeout);
+                                       if (tv_isset(&t->be->srvtimeout)) {
+                                               tv_add(&req->wex, &now, &t->be->srvtimeout);
                                                /* FIXME: to prevent the server from expiring read timeouts during writes,
                                                 * we refresh it. */
                                                rep->rex = req->wex;
@@ -2964,8 +2966,8 @@ int process_srv(struct session *t)
                        /* We must ensure that the read part is still alive when switching
                         * to shutw */
                        EV_FD_SET(t->srv_fd, DIR_RD);
-                       if (t->be->srvtimeout)
-                               tv_ms_add(&rep->rex, &now, t->be->srvtimeout);
+                       if (tv_isset(&t->be->srvtimeout))
+                               tv_add(&rep->rex, &now, &t->be->srvtimeout);
 
                        shutdown(t->srv_fd, SHUT_WR);
                        t->srv_state = SV_STSHUTW;
@@ -3034,14 +3036,14 @@ int process_srv(struct session *t)
                        /* We must ensure that the read part is still alive when switching
                         * to shutw */
                        EV_FD_SET(t->srv_fd, DIR_RD);
-                       if (t->be->srvtimeout)
-                               tv_ms_add(&rep->rex, &now, t->be->srvtimeout);
+                       if (tv_isset(&t->be->srvtimeout))
+                               tv_add(&rep->rex, &now, &t->be->srvtimeout);
 
                        t->srv_state = SV_STSHUTW;
                        return 1;
                }
                /* read timeout */
-               else if (tv_ms_le2(&rep->rex, &now)) {
+               else if (__tv_isle(&rep->rex, &now)) {
                        EV_FD_CLR(t->srv_fd, DIR_RD);
                        tv_eternity(&rep->rex);
                        t->srv_state = SV_STSHUTR;
@@ -3052,15 +3054,15 @@ int process_srv(struct session *t)
                        return 1;
                }       
                /* write timeout */
-               else if (tv_ms_le2(&req->wex, &now)) {
+               else if (__tv_isle(&req->wex, &now)) {
                        EV_FD_CLR(t->srv_fd, DIR_WR);
                        tv_eternity(&req->wex);
                        shutdown(t->srv_fd, SHUT_WR);
                        /* We must ensure that the read part is still alive when switching
                         * to shutw */
                        EV_FD_SET(t->srv_fd, DIR_RD);
-                       if (t->be->srvtimeout)
-                               tv_ms_add(&rep->rex, &now, t->be->srvtimeout);
+                       if (tv_isset(&t->be->srvtimeout))
+                               tv_add(&rep->rex, &now, &t->be->srvtimeout);
                        t->srv_state = SV_STSHUTW;
                        if (!(t->flags & SN_ERR_MASK))
                                t->flags |= SN_ERR_SRVTO;
@@ -3079,8 +3081,8 @@ int process_srv(struct session *t)
                else { /* buffer not empty, there are still data to be transferred */
                        if (EV_FD_COND_S(t->srv_fd, DIR_WR)) {
                                /* restart writing */
-                               if (t->be->srvtimeout) {
-                                       tv_ms_add(&req->wex, &now, t->be->srvtimeout);
+                               if (tv_isset(&t->be->srvtimeout)) {
+                                       tv_add(&req->wex, &now, &t->be->srvtimeout);
                                        /* FIXME: to prevent the server from expiring read timeouts during writes,
                                         * we refresh it. */
                                        rep->rex = req->wex;
@@ -3098,8 +3100,8 @@ int process_srv(struct session *t)
                }
                else {
                        if (EV_FD_COND_S(t->srv_fd, DIR_RD)) {
-                               if (t->be->srvtimeout)
-                                       tv_ms_add(&rep->rex, &now, t->be->srvtimeout);
+                               if (tv_isset(&t->be->srvtimeout))
+                                       tv_add(&rep->rex, &now, &t->be->srvtimeout);
                                else
                                        tv_eternity(&rep->rex);
                        }
@@ -3147,7 +3149,7 @@ int process_srv(struct session *t)
 
                        return 1;
                }
-               else if (tv_ms_le2(&req->wex, &now)) {
+               else if (__tv_isle(&req->wex, &now)) {
                        //EV_FD_CLR(t->srv_fd, DIR_WR);
                        tv_eternity(&req->wex);
                        fd_delete(t->srv_fd);
@@ -3176,8 +3178,8 @@ int process_srv(struct session *t)
                else { /* buffer not empty */
                        if (EV_FD_COND_S(t->srv_fd, DIR_WR)) {
                                /* restart writing */
-                               if (t->be->srvtimeout) {
-                                       tv_ms_add(&req->wex, &now, t->be->srvtimeout);
+                               if (tv_isset(&t->be->srvtimeout)) {
+                                       tv_add(&req->wex, &now, &t->be->srvtimeout);
                                        /* FIXME: to prevent the server from expiring read timeouts during writes,
                                         * we refresh it. */
                                        rep->rex = req->wex;
@@ -3228,7 +3230,7 @@ int process_srv(struct session *t)
 
                        return 1;
                }
-               else if (tv_ms_le2(&rep->rex, &now)) {
+               else if (__tv_isle(&rep->rex, &now)) {
                        //EV_FD_CLR(t->srv_fd, DIR_RD);
                        tv_eternity(&rep->rex);
                        fd_delete(t->srv_fd);
@@ -3255,8 +3257,8 @@ int process_srv(struct session *t)
                }
                else {
                        if (EV_FD_COND_S(t->srv_fd, DIR_RD)) {
-                               if (t->be->srvtimeout)
-                                       tv_ms_add(&rep->rex, &now, t->be->srvtimeout);
+                               if (tv_isset(&t->be->srvtimeout))
+                                       tv_add(&rep->rex, &now, &t->be->srvtimeout);
                                else
                                        tv_eternity(&rep->rex);
                        }
@@ -4375,7 +4377,7 @@ void manage_client_side_cookies(struct session *t, struct buffer *req)
                                                }/* end while(srv) */
                                        }/* end else if server == NULL */
 
-                                       tv_ms_add(&asession_temp->expire, &now, t->be->appsession_timeout);
+                                       tv_add(&asession_temp->expire, &now, &t->be->appsession_timeout);
                                }/* end if ((t->proxy->appsession_name != NULL) ... */
                        }
 
@@ -4835,7 +4837,7 @@ void manage_server_side_cookies(struct session *t, struct buffer *rtr)
                                if (asession_temp->serverid[0] == '\0')
                                        memcpy(asession_temp->serverid, t->srv->id, server_id_len);
                      
-                               tv_ms_add(&asession_temp->expire, &now, t->be->appsession_timeout);
+                               tv_add(&asession_temp->expire, &now, &t->be->appsession_timeout);
 
 #if defined(DEBUG_HASH)
                                print_table(&(t->be->htbl_proxy));
@@ -4997,7 +4999,7 @@ void get_srv_from_appsession(struct session *t, const char *begin, int len)
                pool_free_to(apools.sessid, local_asession.sessid);
        }
        
-       tv_ms_add(&asession_temp->expire, &now, t->be->appsession_timeout);
+       tv_add(&asession_temp->expire, &now, &t->be->appsession_timeout);
        asession_temp->request_count++;
        
 #if defined(DEBUG_HASH)
index 3cc355a84bdb80552a3248655928fdfb1d881371..dd7f993e34e8828c633ceff9aeb9cf0435ecba7c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Proxy variables and functions.
  *
- * Copyright 2000-2006 Willy Tarreau <w@1wt.eu>
+ * Copyright 2000-2007 Willy Tarreau <w@1wt.eu>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -170,17 +170,16 @@ int start_proxies(int verbose)
 /*
  * this function enables proxies when there are enough free sessions,
  * or stops them when the table is full. It is designed to be called from the
- * select_loop(). It returns the time left before next expiration event
- * during stop time, TIME_ETERNITY otherwise.
+ * select_loop(). It returns the date of next expiration event during stop
+ * time, ETERNITY otherwise.
  */
-int maintain_proxies(void)
+void maintain_proxies(struct timeval *next)
 {
        struct proxy *p;
        struct listener *l;
-       int tleft; /* time left */
 
        p = proxy;
-       tleft = TIME_ETERNITY; /* infinite time */
+       tv_eternity(next);
 
        /* if there are enough free sessions, we'll activate proxies */
        if (actconn < global.maxconn) {
@@ -233,13 +232,13 @@ int maintain_proxies(void)
                                        p->state = PR_STSTOPPED;
                                }
                                else {
-                                       tleft = MINTIME(t, tleft);
+                                       tv_bound(next, &p->stop_time);
                                }
                        }
                        p = p->next;
                }
        }
-       return tleft;
+       return;
 }
 
 
index 9b53687de10b5aedffbb8276aa39a5517e840b81..37d3ed85072bddd1d8ed27ac9aa9da2c0534d610 100644 (file)
@@ -45,9 +45,9 @@ unsigned int srv_dynamic_maxconn(const struct server *s)
 /*
  * Manages a server's connection queue. If woken up, will try to dequeue as
  * many pending sessions as possible, and wake them up. The task has nothing
- * else to do, so it always returns TIME_ETERNITY.
+ * else to do, so it always returns ETERNITY.
  */
-int process_srv_queue(struct task *t)
+void process_srv_queue(struct task *t, struct timeval *next)
 {
        struct server *s = (struct server*)t->context;
        struct proxy  *p = s->proxy;
@@ -65,7 +65,7 @@ int process_srv_queue(struct task *t)
                task_wakeup(sess->task);
        }
 
-       return TIME_ETERNITY;
+       tv_eternity(next);
 }
 
 /* Detaches the next pending connection from either a server or a proxy, and
index e420ace348e2b15753ac409b05fb11e8bcfcd480..4691a9c5a452c8621dbd274f41242109c30f49bb 100644 (file)
@@ -165,8 +165,8 @@ int stream_sock_read(int fd) {
         */
 
        if (b->flags & BF_PARTIAL_READ) {
-               if (b->rto) {
-                       tv_ms_add(&b->rex, &now, b->rto);
+               if (tv_isset(&b->rto)) {
+                       tv_add(&b->rex, &now, &b->rto);
                        goto out_wakeup;
                }
        out_eternity:
@@ -315,8 +315,8 @@ int stream_sock_write(int fd) {
         */
 
        if (b->flags & BF_PARTIAL_WRITE) {
-               if (b->wto) {
-                       tv_ms_add(&b->wex, &now, b->wto);
+               if (tv_isset(&b->wto)) {
+                       tv_add(&b->wex, &now, &b->wto);
                        /* FIXME: to prevent the client from expiring read timeouts during writes,
                         * we refresh it. A solution would be to merge read+write timeouts into a
                         * unique one, although that needs some study particularly on full-duplex
index 89055812848cbf31decede2025f17a1043246c37..953da6c7c5b76be03846c3cceba17b1d1f0946f8 100644 (file)
@@ -15,6 +15,7 @@
 #include <common/standard.h>
 #include <common/time.h>
 
+#include <proto/proxy.h>
 #include <proto/task.h>
 #include <types/task.h>
 
@@ -23,9 +24,6 @@
 #include <import/tree.h>
 
 
-/* FIXME : this should be removed very quickly ! */
-extern int maintain_proxies(void);
-
 void **pool_task= NULL;
 void **pool_tree64 = NULL;
 static struct ultree *stack[LLONGBITS];
@@ -47,6 +45,7 @@ struct task *_task_wakeup(struct task *t)
 {
        return __task_wakeup(t);
 }
+
 /*
  * task_queue()
  *
@@ -80,19 +79,15 @@ struct task *task_queue(struct task *task)
 
 /*
  * Extract all expired timers from the wait queue, and wakes up all
- * associated tasks.
- * Returns the time to wait for next task (next_time).
- *
- * FIXME: Use an alternative queue for ETERNITY tasks.
+ * associated tasks. Returns the date of next event (or eternity).
  *
  */
-int wake_expired_tasks()
+void wake_expired_tasks(struct timeval *next)
 {
        __label__ out;
        int slen;
        struct task *task;
        void *data;
-       int next_time;
 
        /*
         * Hint: tasks are *rarely* expired. So we can try to optimize
@@ -102,19 +97,19 @@ int wake_expired_tasks()
        if (likely(timer_wq.data != NULL)) {
                task = LIST_ELEM(timer_wq.data, struct task *, qlist);
                if (likely(__tv_isge(&task->expire, &now) > 0)) {
-                       next_time = tv_ms_remain(&now, &task->expire);
+                       __tv_remain(&now, &task->expire, next);
                        goto out;
                }
        }
 
        /* OK we lose. Let's scan the tree then. */
-       next_time = TIME_ETERNITY;
+       tv_eternity(next);
 
        tree64_foreach(&timer_wq, data, stack, slen) {
                task = LIST_ELEM(data, struct task *, qlist);
 
                if (__tv_isgt(&task->expire, &now)) {
-                       next_time = tv_ms_remain(&now, &task->expire);
+                       __tv_remain2(&now, &task->expire, next);
                        break;
                }
 
@@ -131,10 +126,7 @@ int wake_expired_tasks()
                }
        }
  out:
-       /* Ensure that we don't report sub-millisecond timeouts */
-       if (next_time != TIME_ETERNITY)
-               next_time++;
-       return next_time;
+       return;
 }
 
 /*
@@ -142,17 +134,16 @@ int wake_expired_tasks()
  *   - wake up all expired tasks
  *   - call all runnable tasks
  *   - call maintain_proxies() to enable/disable the listeners
- *   - return the delay till next event in ms, -1 = wait indefinitely
+ *   - return the date of next event in <next> or eternity.
  *
  */
-int process_runnable_tasks()
+void process_runnable_tasks(struct timeval *next)
 {
-       int next_time;
-       int time2;
+       struct timeval temp;
        struct task *t;
        void *queue;
 
-       next_time = wake_expired_tasks();
+       wake_expired_tasks(next);
        /* process each task in the run queue now. Each task may be deleted
         * since we only use the run queue's head. Note that any task can be
         * woken up by any other task and it will be processed immediately
@@ -161,21 +152,20 @@ int process_runnable_tasks()
 
        queue = run_queue;
        foreach_dlist_item(t, queue, struct task *, qlist) {
-               int temp_time;
-
                DLIST_DEL(&t->qlist);
                t->qlist.p = NULL;
 
                t->state = TASK_IDLE;
-               temp_time = t->process(t);
-               next_time = MINTIME(temp_time, next_time);
+               t->process(t, &temp);
+               tv_bound(next, &temp);
        }
 
        /* maintain all proxies in a consistent state. This should quickly
         * become a task because it becomes expensive when there are huge
         * numbers of proxies. */
-       time2 = maintain_proxies();
-       return MINTIME(time2, next_time);
+       maintain_proxies(&temp);
+       tv_bound(next, &temp);
+       return;
 }
 
 /*
index 262bc44911ea94bb51fe1d7dea0d004735c7f222..cf3d5cff69b08b5904b582a7287b461add7253e5 100644 (file)
@@ -94,6 +94,33 @@ REGPRM2 unsigned long _tv_ms_elapsed(const struct timeval *tv1, const struct tim
        return __tv_ms_elapsed(tv1, tv2);
 }
 
+/*
+ * adds <inc> to <from>, set the result to <tv> and returns a pointer <tv>
+ */
+REGPRM3 struct timeval *_tv_add(struct timeval *tv, const struct timeval *from, const struct timeval *inc)
+{
+       return __tv_add(tv, from, inc);
+}
+
+/*
+ * Computes the remaining time between tv1=now and event=tv2. if tv2 is passed,
+ * 0 is returned. The result is stored into tv.
+ */
+REGPRM3 struct timeval *_tv_remain(const struct timeval *tv1, const struct timeval *tv2, struct timeval *tv)
+{
+       return __tv_remain(tv1, tv2, tv);
+}
+
+/*
+ * Computes the remaining time between tv1=now and event=tv2. if tv2 is passed,
+ * 0 is returned. The result is stored into tv. Returns ETERNITY if tv2 is
+ * eternity.
+ */
+REGPRM3 struct timeval *_tv_remain2(const struct timeval *tv1, const struct timeval *tv2, struct timeval *tv)
+{
+       return __tv_remain2(tv1, tv2, tv);
+}
+
 /*
  * Local variables:
  *  c-indent-level: 8