]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[OPTIM] checks: try to detect the end of response without polling again
authorWilly Tarreau <w@1wt.eu>
Tue, 16 Mar 2010 19:32:04 +0000 (20:32 +0100)
committerWilly Tarreau <w@1wt.eu>
Tue, 16 Mar 2010 21:57:27 +0000 (22:57 +0100)
Since the recv() call returns every time it succeeds, we always need
to calls with one intermediate poll before detecting the end of response :

  20:20:03.958207 recv(7, "HTTP/1.1 200\r\nConnection: close\r\n"..., 8030, 0) = 145
  20:20:03.958365 epoll_wait(3, {{EPOLLIN, {u32=7, u64=7}}}, 8, 1000) = 1
  20:20:03.958543 gettimeofday({1268767203, 958626}, NULL) = 0
  20:20:03.958694 recv(7, ""..., 7885, 0) = 0
  20:20:03.958833 shutdown(7, 2 /* send and receive */) = 0

Let's read as long as we can, that way we can detect end of connections
in the same call, which is much more efficient especially for LBs with
hundreds of servers :

  20:29:58.797019 recv(7, "HTTP/1.1 200\r\nConnection: close\r\n"..., 8030, 0) = 145
  20:29:58.797182 recv(7, ""..., 7885, 0) = 0
  20:29:58.797356 shutdown(7, 2 /* send and receive */) = 0

src/checks.c

index d885c7d882e7e8f3e76057805482e2ec908a8578..eeed75af4028c9865b3563f27413a43784c978f3 100644 (file)
@@ -865,10 +865,6 @@ static int event_srv_chk_r(int fd)
        struct task *t = fdtab[fd].owner;
        struct server *s = t->context;
        char *desc;
-       char *buffer;
-       int buffer_remaining;
-
-       len = -1;
 
        if (unlikely((s->result & SRV_CHK_ERROR) ||
                     (fdtab[fd].state == FD_STERROR) ||
@@ -889,13 +885,12 @@ static int event_srv_chk_r(int fd)
         * that there is free space remaining. If the buffer is full, proceed
         * with running the checks without attempting another socket read.
         */
-       buffer = s->check_data + s->check_data_len;
-       buffer_remaining = BUFSIZE - s->check_data_len;
 
-       if (buffer_remaining > 0)
-               len = recv(fd, buffer, buffer_remaining, 0);
-       else
-               len = 0;
+       for (len = 0; s->check_data_len < BUFSIZE; s->check_data_len += len) {
+               len = recv(fd, s->check_data + s->check_data_len, BUFSIZE - s->check_data_len, 0);
+               if (len <= 0)
+                       break;
+       }
 
        if (len < 0) {                  /* recv returned an error */
                if (errno == EAGAIN) {
@@ -908,19 +903,13 @@ static int event_srv_chk_r(int fd)
                        set_server_check_status(s, HCHK_STATUS_SOCKERR, NULL);
                goto out_wakeup;
        }
-       else if (len != 0)              /* recv hasn't seen end of connection */
-       {
-               s->check_data_len += len;
-               fdtab[fd].ev &= ~FD_POLL_IN;
-               return 0;
-       }
 
        /* Full response received.
         * Terminate string in check_data buffer... */
        if (s->check_data_len < BUFSIZE)
-               *buffer = '\0';
+               s->check_data[s->check_data_len] = '\0';
        else
-               *(buffer - 1) = '\0';
+               s->check_data[s->check_data_len - 1] = '\0';
 
        /* Close the connection... */
        int shut = shutdown(fd, SHUT_RDWR);