~ubuntu-branches/ubuntu/quantal/haproxy/quantal

« back to all changes in this revision

Viewing changes to src/checks.c

  • Committer: Bazaar Package Importer
  • Author(s): Arnaud Cornet
  • Date: 2008-03-09 21:30:29 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20080309213029-8oupnrc607mg5uqw
Tags: 1.3.14.3-1
* New Upstream Version
* Add status argument support to init-script to conform to LSB.
* Cleanup pidfile after stop in init script. Init script return code fixups.

Show diffs side-by-side

added added

removed removed

Lines of Context:
10
10
 *
11
11
 */
12
12
 
 
13
#include <assert.h>
13
14
#include <errno.h>
14
15
#include <fcntl.h>
15
16
#include <stdio.h>
 
17
#include <stdlib.h>
16
18
#include <string.h>
 
19
#include <time.h>
17
20
#include <unistd.h>
18
21
#include <sys/socket.h>
19
22
#include <netinet/in.h>
43
46
#include <import/ip_tproxy.h>
44
47
#endif
45
48
 
 
49
/* sends a log message when a backend goes down, and also sets last
 
50
 * change date.
 
51
 */
 
52
static void set_backend_down(struct proxy *be)
 
53
{
 
54
        be->last_change = now.tv_sec;
 
55
        be->down_trans++;
 
56
 
 
57
        Alert("%s '%s' has no server available!\n", proxy_type_str(be), be->id);
 
58
        send_log(be, LOG_EMERG, "%s %s has no server available!\n", proxy_type_str(be), be->id);
 
59
}
 
60
 
 
61
/* Redistribute pending connections when a server goes down. The number of
 
62
 * connections redistributed is returned.
 
63
 */
 
64
static int redistribute_pending(struct server *s)
 
65
{
 
66
        struct pendconn *pc, *pc_bck, *pc_end;
 
67
        int xferred = 0;
 
68
 
 
69
        FOREACH_ITEM_SAFE(pc, pc_bck, &s->pendconns, pc_end, struct pendconn *, list) {
 
70
                struct session *sess = pc->sess;
 
71
                if (sess->be->options & PR_O_REDISP) {
 
72
                        /* The REDISP option was specified. We will ignore
 
73
                         * cookie and force to balance or use the dispatcher.
 
74
                         */
 
75
                        sess->flags &= ~(SN_DIRECT | SN_ASSIGNED | SN_ADDR_SET);
 
76
                        sess->srv = NULL; /* it's left to the dispatcher to choose a server */
 
77
                        http_flush_cookie_flags(&sess->txn);
 
78
                        pendconn_free(pc);
 
79
                        task_wakeup(sess->task);
 
80
                        xferred++;
 
81
                }
 
82
        }
 
83
        return xferred;
 
84
}
 
85
 
 
86
/* Check for pending connections at the backend, and assign some of them to
 
87
 * the server coming up. The server's weight is checked before being assigned
 
88
 * connections it may not be able to handle. The total number of transferred
 
89
 * connections is returned.
 
90
 */
 
91
static int check_for_pending(struct server *s)
 
92
{
 
93
        int xferred;
 
94
 
 
95
        if (!s->eweight)
 
96
                return 0;
 
97
 
 
98
        for (xferred = 0; !s->maxconn || xferred < srv_dynamic_maxconn(s); xferred++) {
 
99
                struct session *sess;
 
100
                struct pendconn *p;
 
101
 
 
102
                p = pendconn_from_px(s->proxy);
 
103
                if (!p)
 
104
                        break;
 
105
                p->sess->srv = s;
 
106
                sess = p->sess;
 
107
                pendconn_free(p);
 
108
                task_wakeup(sess->task);
 
109
        }
 
110
        return xferred;
 
111
}
46
112
 
47
113
/* Sets server <s> down, notifies by all available means, recounts the
48
114
 * remaining servers on the proxy and transfers queued sessions whenever
49
 
 * possible to other servers.
 
115
 * possible to other servers. It automatically recomputes the number of
 
116
 * servers, but not the map.
50
117
 */
51
118
static void set_server_down(struct server *s)
52
119
{
53
 
        struct pendconn *pc, *pc_bck, *pc_end;
54
 
        struct session *sess;
55
120
        int xferred;
56
121
 
57
 
        s->state &= ~SRV_RUNNING;
58
 
 
59
122
        if (s->health == s->rise) {
60
 
                recount_servers(s->proxy);
61
 
                recalc_server_map(s->proxy);
 
123
                int srv_was_paused = s->state & SRV_GOINGDOWN;
 
124
 
 
125
                s->last_change = now.tv_sec;
 
126
                s->state &= ~(SRV_RUNNING | SRV_GOINGDOWN);
 
127
                s->proxy->lbprm.set_server_status_down(s);
62
128
 
63
129
                /* we might have sessions queued on this server and waiting for
64
130
                 * a connection. Those which are redispatchable will be queued
65
131
                 * to another server or to the proxy itself.
66
132
                 */
67
 
                xferred = 0;
68
 
                FOREACH_ITEM_SAFE(pc, pc_bck, &s->pendconns, pc_end, struct pendconn *, list) {
69
 
                        sess = pc->sess;
70
 
                        if ((sess->be->options & PR_O_REDISP)) {
71
 
                                /* The REDISP option was specified. We will ignore
72
 
                                 * cookie and force to balance or use the dispatcher.
73
 
                                 */
74
 
                                sess->flags &= ~(SN_DIRECT | SN_ASSIGNED | SN_ADDR_SET);
75
 
                                sess->srv = NULL; /* it's left to the dispatcher to choose a server */
76
 
                                http_flush_cookie_flags(&sess->txn);
77
 
                                pendconn_free(pc);
78
 
                                task_wakeup(sess->task);
79
 
                                xferred++;
80
 
                        }
81
 
                }
82
 
 
 
133
                xferred = redistribute_pending(s);
83
134
                sprintf(trash, "%sServer %s/%s is DOWN. %d active and %d backup servers left.%s"
84
135
                        " %d sessions active, %d requeued, %d remaining in queue.\n",
85
136
                        s->state & SRV_BACKUP ? "Backup " : "",
88
139
                        s->cur_sess, xferred, s->nbpend);
89
140
 
90
141
                Warning("%s", trash);
91
 
                send_log(s->proxy, LOG_ALERT, "%s", trash);
92
 
        
93
 
                if (s->proxy->srv_bck == 0 && s->proxy->srv_act == 0) {
94
 
                        Alert("%s '%s' has no server available !\n", proxy_type_str(s->proxy), s->proxy->id);
95
 
                        send_log(s->proxy, LOG_EMERG, "%s %s has no server available !\n", proxy_type_str(s->proxy), s->proxy->id);
96
 
                }
 
142
 
 
143
                /* we don't send an alert if the server was previously paused */
 
144
                if (srv_was_paused)
 
145
                        send_log(s->proxy, LOG_NOTICE, "%s", trash);
 
146
                else
 
147
                        send_log(s->proxy, LOG_ALERT, "%s", trash);
 
148
 
 
149
                if (s->proxy->srv_bck == 0 && s->proxy->srv_act == 0)
 
150
                        set_backend_down(s->proxy);
 
151
 
97
152
                s->down_trans++;
98
153
        }
99
154
        s->health = 0; /* failure */
103
158
/*
104
159
 * This function is used only for server health-checks. It handles
105
160
 * the connection acknowledgement. If the proxy requires HTTP health-checks,
106
 
 * it sends the request. In other cases, it returns 1 in s->result if the
107
 
 * socket is OK, or -1 if an error occured.
 
161
 * it sends the request. In other cases, it fills s->result with SRV_CHK_*.
108
162
 * The function itself returns 0 if it needs some polling before being called
109
163
 * again, otherwise 1.
110
164
 */
119
173
 
120
174
        /* here, we know that the connection is established */
121
175
 
122
 
        if (s->result != -1) {
 
176
        if (!(s->result & SRV_CHK_ERROR)) {
123
177
                /* we don't want to mark 'UP' a server on which we detected an error earlier */
124
178
                if ((s->proxy->options & PR_O_HTTP_CHK) ||
125
179
                    (s->proxy->options & PR_O_SSL3_CHK) ||
175
229
                                goto out_error;
176
230
 
177
231
                        /* good TCP connection is enough */
178
 
                        s->result = 1;
 
232
                        s->result |= SRV_CHK_RUNNING;
179
233
                        goto out_wakeup;
180
234
                }
181
235
        }
183
237
        task_wakeup(t);
184
238
 out_nowake:
185
239
        EV_FD_CLR(fd, DIR_WR);   /* nothing more to write */
186
 
        fdtab[fd].ev &= ~FD_POLL_WR;
 
240
        fdtab[fd].ev &= ~FD_POLL_OUT;
187
241
        return 1;
188
242
 out_poll:
189
243
        /* The connection is still pending. We'll have to poll it
190
244
         * before attempting to go further. */
191
 
        fdtab[fd].ev &= ~FD_POLL_WR;
 
245
        fdtab[fd].ev &= ~FD_POLL_OUT;
192
246
        return 0;
193
247
 out_error:
194
 
        s->result = -1;
 
248
        s->result |= SRV_CHK_ERROR;
195
249
        fdtab[fd].state = FD_STERROR;
196
250
        goto out_wakeup;
197
251
}
199
253
 
200
254
/*
201
255
 * This function is used only for server health-checks. It handles the server's
202
 
 * reply to an HTTP request or SSL HELLO. It returns 1 in s->result if the
203
 
 * server replies HTTP 2xx or 3xx (valid responses), or if it returns at least
204
 
 * 5 bytes in response to SSL HELLO. The principle is that this is enough to
205
 
 * distinguish between an SSL server and a pure TCP relay. All other cases will
206
 
 * return -1. The function returns 0 if it needs to be called again after some
207
 
 * polling, otherwise non-zero..
 
256
 * reply to an HTTP request or SSL HELLO. It sets s->result to SRV_CHK_RUNNING
 
257
 * if an HTTP server replies HTTP 2xx or 3xx (valid responses), if an SMTP
 
258
 * server returns 2xx, or if an SSL server returns at least 5 bytes in response
 
259
 * to an SSL HELLO (the principle is that this is enough to distinguish between
 
260
 * an SSL server and a pure TCP relay). All other cases will set s->result to
 
261
 * SRV_CHK_ERROR. The function returns 0 if it needs to be called again after
 
262
 * some polling, otherwise non-zero..
208
263
 */
209
264
static int event_srv_chk_r(int fd)
210
265
{
211
266
        __label__ out_wakeup;
212
 
        char reply[64];
213
 
        int len, result;
 
267
        int len;
214
268
        struct task *t = fdtab[fd].owner;
215
269
        struct server *s = t->context;
216
270
        int skerr;
217
271
        socklen_t lskerr = sizeof(skerr);
218
272
 
219
 
        result = len = -1;
 
273
        len = -1;
220
274
 
221
 
        if (unlikely(fdtab[fd].state == FD_STERROR ||
 
275
        if (unlikely((s->result & SRV_CHK_ERROR) ||
 
276
                     (fdtab[fd].state == FD_STERROR) ||
222
277
                     (fdtab[fd].ev & FD_POLL_ERR) ||
223
278
                     (getsockopt(fd, SOL_SOCKET, SO_ERROR, &skerr, &lskerr) == -1) ||
224
279
                     (skerr != 0))) {
225
280
                /* in case of TCP only, this tells us if the connection failed */
226
 
                s->result = -1;
227
 
                fdtab[fd].state = FD_STERROR;
 
281
                s->result |= SRV_CHK_ERROR;
228
282
                goto out_wakeup;
229
283
        }
230
284
 
231
285
#ifndef MSG_NOSIGNAL
232
 
        len = recv(fd, reply, sizeof(reply), 0);
 
286
        len = recv(fd, trash, sizeof(trash), 0);
233
287
#else
234
288
        /* Warning! Linux returns EAGAIN on SO_ERROR if data are still available
235
289
         * but the connection was closed on the remote end. Fortunately, recv still
236
290
         * works correctly and we don't need to do the getsockopt() on linux.
237
291
         */
238
 
        len = recv(fd, reply, sizeof(reply), MSG_NOSIGNAL);
 
292
        len = recv(fd, trash, sizeof(trash), MSG_NOSIGNAL);
239
293
#endif
240
294
        if (unlikely(len < 0 && errno == EAGAIN)) {
241
295
                /* we want some polling to happen first */
242
 
                fdtab[fd].ev &= ~FD_POLL_RD;
 
296
                fdtab[fd].ev &= ~FD_POLL_IN;
243
297
                return 0;
244
298
        }
245
299
 
246
 
        if ((s->proxy->options & PR_O_HTTP_CHK) && (len >= sizeof("HTTP/1.0 000")) &&
247
 
             (memcmp(reply, "HTTP/1.", 7) == 0) && (reply[9] == '2' || reply[9] == '3')) {
248
 
                /* HTTP/1.X 2xx or 3xx */
249
 
                result = 1;
250
 
        }
251
 
        else if ((s->proxy->options & PR_O_SSL3_CHK) && (len >= 5) &&
252
 
                 (reply[0] == 0x15 || reply[0] == 0x16)) {
253
 
                /* SSLv3 alert or handshake */
254
 
                result = 1;
255
 
        }
256
 
        else if ((s->proxy->options & PR_O_SMTP_CHK) && (len >= 3) &&
257
 
                   (reply[0] == '2')) /* 2xx (should be 250) */ {
258
 
                result = 1;
259
 
        }
260
 
 
261
 
        if (result == -1)
 
300
        /* Note: the response will only be accepted if read at once */
 
301
        if (s->proxy->options & PR_O_HTTP_CHK) {
 
302
                /* Check if the server speaks HTTP 1.X */
 
303
                if ((len < strlen("HTTP/1.0 000\r")) ||
 
304
                    (memcmp(trash, "HTTP/1.", 7) != 0)) {
 
305
                        s->result |= SRV_CHK_ERROR;
 
306
                        goto out_wakeup;
 
307
                }
 
308
 
 
309
                /* check the reply : HTTP/1.X 2xx and 3xx are OK */
 
310
                if (trash[9] == '2' || trash[9] == '3')
 
311
                        s->result |= SRV_CHK_RUNNING;
 
312
                else if ((s->proxy->options & PR_O_DISABLE404) &&
 
313
                         (s->state & SRV_RUNNING) &&
 
314
                         (memcmp(&trash[9], "404", 3) == 0)) {
 
315
                        /* 404 may be accepted as "stopping" only if the server was up */
 
316
                        s->result |= SRV_CHK_RUNNING | SRV_CHK_DISABLE;
 
317
                }
 
318
                else
 
319
                        s->result |= SRV_CHK_ERROR;
 
320
        }
 
321
        else if (s->proxy->options & PR_O_SSL3_CHK) {
 
322
                /* Check for SSLv3 alert or handshake */
 
323
                if ((len >= 5) && (trash[0] == 0x15 || trash[0] == 0x16))
 
324
                        s->result |= SRV_CHK_RUNNING;
 
325
                else
 
326
                        s->result |= SRV_CHK_ERROR;
 
327
        }
 
328
        else if (s->proxy->options & PR_O_SMTP_CHK) {
 
329
                /* Check for SMTP code 2xx (should be 250) */
 
330
                if ((len >= 3) && (trash[0] == '2'))
 
331
                        s->result |= SRV_CHK_RUNNING;
 
332
                else
 
333
                        s->result |= SRV_CHK_ERROR;
 
334
        }
 
335
        else {
 
336
                /* other checks are valid if the connection succeeded anyway */
 
337
                s->result |= SRV_CHK_RUNNING;
 
338
        }
 
339
 
 
340
 out_wakeup:
 
341
        if (s->result & SRV_CHK_ERROR)
262
342
                fdtab[fd].state = FD_STERROR;
263
343
 
264
 
        if (s->result != -1)
265
 
                s->result = result;
266
 
 
267
 
 out_wakeup:
268
344
        EV_FD_CLR(fd, DIR_RD);
269
345
        task_wakeup(t);
270
 
        fdtab[fd].ev &= ~FD_POLL_RD;
 
346
        fdtab[fd].ev &= ~FD_POLL_IN;
271
347
        return 1;
272
348
}
273
349
 
280
356
        __label__ new_chk, out;
281
357
        struct server *s = t->context;
282
358
        struct sockaddr_in sa;
 
359
        int xferred;
283
360
        int fd;
 
361
        int rv;
284
362
 
285
363
        //fprintf(stderr, "process_chk: task=%p\n", t);
286
364
 
306
384
                }
307
385
 
308
386
                /* we'll initiate a new check */
309
 
                s->result = 0; /* no result yet */
 
387
                s->result = SRV_CHK_UNKNOWN; /* no result yet */
310
388
                if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) != -1) {
311
389
                        if ((fd < global.maxsock) &&
312
390
                            (fcntl(fd, F_SETFL, O_NONBLOCK) != -1) &&
313
391
                            (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *) &one, sizeof(one)) != -1)) {
314
392
                                //fprintf(stderr, "process_chk: 3\n");
315
393
 
 
394
                                if (s->proxy->options & PR_O_TCP_NOLING) {
 
395
                                        /* We don't want to useless data */
 
396
                                        setsockopt(fd, SOL_SOCKET, SO_LINGER, (struct linger *) &nolinger, sizeof(struct linger));
 
397
                                }
316
398
                                
317
399
                                if (s->check_addr.sin_addr.s_addr)
318
400
                                        /* we'll connect to the check addr specified on the server */
333
415
                                        if (bind(fd, (struct sockaddr *)&s->source_addr, sizeof(s->source_addr)) == -1) {
334
416
                                                Alert("Cannot bind to source address before connect() for server %s/%s. Aborting.\n",
335
417
                                                      s->proxy->id, s->id);
336
 
                                                s->result = -1;
 
418
                                                s->result |= SRV_CHK_ERROR;
337
419
                                        }
338
420
#ifdef CONFIG_HAP_CTTPROXY
339
421
                                        if ((s->state & SRV_TPROXY_MASK) == SRV_TPROXY_ADDR) {
352
434
                                                    setsockopt(fd, SOL_IP, IP_TPROXY, &itp2, sizeof(itp2)) == -1) {
353
435
                                                        Alert("Cannot bind to tproxy source address before connect() for server %s/%s. Aborting.\n",
354
436
                                                              s->proxy->id, s->id);
355
 
                                                        s->result = -1;
 
437
                                                        s->result |= SRV_CHK_ERROR;
356
438
                                                }
357
439
                                        }
358
440
#endif
362
444
                                        if (bind(fd, (struct sockaddr *)&s->proxy->source_addr, sizeof(s->proxy->source_addr)) == -1) {
363
445
                                                Alert("Cannot bind to source address before connect() for %s '%s'. Aborting.\n",
364
446
                                                      proxy_type_str(s->proxy), s->proxy->id);
365
 
                                                s->result = -1;
 
447
                                                s->result |= SRV_CHK_ERROR;
366
448
                                        }
367
449
#ifdef CONFIG_HAP_CTTPROXY
368
450
                                        if ((s->proxy->options & PR_O_TPXY_MASK) == PR_O_TPXY_ADDR) {
370
452
                                                memset(&itp1, 0, sizeof(itp1));
371
453
                                                
372
454
                                                itp1.op = TPROXY_ASSIGN;
373
 
                                                itp1.v.addr.faddr = s->tproxy_addr.sin_addr;
374
 
                                                itp1.v.addr.fport = s->tproxy_addr.sin_port;
 
455
                                                itp1.v.addr.faddr = s->proxy->tproxy_addr.sin_addr;
 
456
                                                itp1.v.addr.fport = s->proxy->tproxy_addr.sin_port;
375
457
                                                
376
458
                                                /* set connect flag on socket */
377
459
                                                itp2.op = TPROXY_FLAGS;
381
463
                                                    setsockopt(fd, SOL_IP, IP_TPROXY, &itp2, sizeof(itp2)) == -1) {
382
464
                                                        Alert("Cannot bind to tproxy source address before connect() for %s '%s'. Aborting.\n",
383
465
                                                              proxy_type_str(s->proxy), s->proxy->id);
384
 
                                                        s->result = -1;
 
466
                                                        s->result |= SRV_CHK_ERROR;
385
467
                                                }
386
468
                                        }
387
469
#endif
388
470
                                }
389
471
 
390
 
                                if (!s->result) {
 
472
                                if (s->result == SRV_CHK_UNKNOWN) {
391
473
                                        if ((connect(fd, (struct sockaddr *)&sa, sizeof(sa)) != -1) || (errno == EINPROGRESS)) {
392
474
                                                /* OK, connection in progress or established */
393
475
                        
400
482
                                                fdtab[fd].cb[DIR_RD].b = NULL;
401
483
                                                fdtab[fd].cb[DIR_WR].f = &event_srv_chk_w;
402
484
                                                fdtab[fd].cb[DIR_WR].b = NULL;
 
485
                                                fdtab[fd].peeraddr = (struct sockaddr *)&sa;
 
486
                                                fdtab[fd].peerlen = sizeof(sa);
403
487
                                                fdtab[fd].state = FD_STCONN; /* connection in progress */
404
 
                                                fdtab[fd].ev = 0;
405
488
                                                EV_FD_SET(fd, DIR_WR);  /* for connect status */
406
489
#ifdef DEBUG_FULL
407
490
                                                assert (!EV_FD_ISSET(fd, DIR_RD));
413
496
                                                return;
414
497
                                        }
415
498
                                        else if (errno != EALREADY && errno != EISCONN && errno != EAGAIN) {
416
 
                                                s->result = -1;    /* a real error */
 
499
                                                s->result |= SRV_CHK_ERROR;    /* a real error */
417
500
                                        }
418
501
                                }
419
502
                        }
420
503
                        close(fd); /* socket creation error */
421
504
                }
422
505
 
423
 
                if (!s->result) { /* nothing done */
 
506
                if (s->result == SRV_CHK_UNKNOWN) { /* nothing done */
424
507
                        //fprintf(stderr, "process_chk: 6\n");
425
508
                        while (tv_isle(&t->expire, &now))
426
509
                                tv_ms_add(&t->expire, &t->expire, s->inter);
444
527
        else {
445
528
                //fprintf(stderr, "process_chk: 8\n");
446
529
                /* there was a test running */
447
 
                if (s->result > 0) { /* good server detected */
 
530
                if ((s->result & (SRV_CHK_ERROR|SRV_CHK_RUNNING)) == SRV_CHK_RUNNING) { /* good server detected */
448
531
                        //fprintf(stderr, "process_chk: 9\n");
449
 
                        s->health++; /* was bad, stays for a while */
450
 
                        if (s->health >= s->rise) {
451
 
                                s->state |= SRV_RUNNING;
 
532
 
 
533
                        if (s->state & SRV_WARMINGUP) {
 
534
                                if (now.tv_sec < s->last_change || now.tv_sec >= s->last_change + s->slowstart) {
 
535
                                        s->state &= ~SRV_WARMINGUP;
 
536
                                        if (s->proxy->lbprm.algo & BE_LB_PROP_DYN)
 
537
                                                s->eweight = s->uweight * BE_WEIGHT_SCALE;
 
538
                                        if (s->proxy->lbprm.update_server_eweight)
 
539
                                                s->proxy->lbprm.update_server_eweight(s);
 
540
                                }
 
541
                                else if (s->proxy->lbprm.algo & BE_LB_PROP_DYN) {
 
542
                                        /* for dynamic algorithms, let's update the weight */
 
543
                                        s->eweight = (BE_WEIGHT_SCALE * (now.tv_sec - s->last_change) +
 
544
                                                      s->slowstart - 1) / s->slowstart;
 
545
                                        s->eweight *= s->uweight;
 
546
                                        if (s->proxy->lbprm.update_server_eweight)
 
547
                                                s->proxy->lbprm.update_server_eweight(s);
 
548
                                }
 
549
                                /* probably that we can refill this server with a bit more connections */
 
550
                                check_for_pending(s);
 
551
                        }
 
552
 
 
553
                        /* we may have to add/remove this server from the LB group */
 
554
                        if ((s->state & SRV_RUNNING) && (s->proxy->options & PR_O_DISABLE404)) {
 
555
                                if ((s->state & SRV_GOINGDOWN) &&
 
556
                                    ((s->result & (SRV_CHK_RUNNING|SRV_CHK_DISABLE)) == SRV_CHK_RUNNING)) {
 
557
                                        /* server enabled again */
 
558
                                        s->state &= ~SRV_GOINGDOWN;
 
559
                                        s->proxy->lbprm.set_server_status_up(s);
 
560
 
 
561
                                        /* check if we can handle some connections queued at the proxy. We
 
562
                                         * will take as many as we can handle.
 
563
                                         */
 
564
                                        xferred = check_for_pending(s);
 
565
 
 
566
                                        sprintf(trash,
 
567
                                                "Load-balancing on %sServer %s/%s is enabled again. %d active and %d backup servers online.%s"
 
568
                                                " %d sessions requeued, %d total in queue.\n",
 
569
                                                s->state & SRV_BACKUP ? "Backup " : "",
 
570
                                                s->proxy->id, s->id, s->proxy->srv_act, s->proxy->srv_bck,
 
571
                                                (s->proxy->srv_bck && !s->proxy->srv_act) ? " Running on backup." : "",
 
572
                                                xferred, s->nbpend);
 
573
 
 
574
                                        Warning("%s", trash);
 
575
                                        send_log(s->proxy, LOG_NOTICE, "%s", trash);
 
576
                                }
 
577
                                else if (!(s->state & SRV_GOINGDOWN) &&
 
578
                                         ((s->result & (SRV_CHK_RUNNING | SRV_CHK_DISABLE)) ==
 
579
                                          (SRV_CHK_RUNNING | SRV_CHK_DISABLE))) {
 
580
                                        /* server disabled */
 
581
                                        s->state |= SRV_GOINGDOWN;
 
582
                                        s->proxy->lbprm.set_server_status_down(s);
 
583
 
 
584
                                        /* we might have sessions queued on this server and waiting for
 
585
                                         * a connection. Those which are redispatchable will be queued
 
586
                                         * to another server or to the proxy itself.
 
587
                                         */
 
588
                                        xferred = redistribute_pending(s);
 
589
 
 
590
                                        sprintf(trash,
 
591
                                                "Load-balancing on %sServer %s/%s is disabled. %d active and %d backup servers online.%s"
 
592
                                                " %d sessions requeued, %d total in queue.\n",
 
593
                                                s->state & SRV_BACKUP ? "Backup " : "",
 
594
                                                s->proxy->id, s->id, s->proxy->srv_act, s->proxy->srv_bck,
 
595
                                                (s->proxy->srv_bck && !s->proxy->srv_act) ? " Running on backup." : "",
 
596
                                                xferred, s->nbpend);
 
597
 
 
598
                                        Warning("%s", trash);
 
599
 
 
600
                                        send_log(s->proxy, LOG_NOTICE, "%s", trash);
 
601
                                        if (!s->proxy->srv_bck && !s->proxy->srv_act)
 
602
                                                set_backend_down(s->proxy);
 
603
                                }
 
604
                        }
 
605
 
 
606
                        if (s->health < s->rise + s->fall - 1) {
 
607
                                s->health++; /* was bad, stays for a while */
452
608
 
453
609
                                if (s->health == s->rise) {
454
 
                                        int xferred;
455
 
 
456
 
                                        recount_servers(s->proxy);
457
 
                                        recalc_server_map(s->proxy);
 
610
                                        if (s->proxy->srv_bck == 0 && s->proxy->srv_act == 0) {
 
611
                                                if (s->proxy->last_change < now.tv_sec)         // ignore negative times
 
612
                                                        s->proxy->down_time += now.tv_sec - s->proxy->last_change;
 
613
                                                s->proxy->last_change = now.tv_sec;
 
614
                                        }
 
615
 
 
616
                                        if (s->last_change < now.tv_sec)                        // ignore negative times
 
617
                                                s->down_time += now.tv_sec - s->last_change;
 
618
 
 
619
                                        s->last_change = now.tv_sec;
 
620
                                        s->state |= SRV_RUNNING;
 
621
                                        if (s->slowstart > 0) {
 
622
                                                s->state |= SRV_WARMINGUP;
 
623
                                                if (s->proxy->lbprm.algo & BE_LB_PROP_DYN) {
 
624
                                                        /* For dynamic algorithms, start at the first step of the weight,
 
625
                                                         * without multiplying by BE_WEIGHT_SCALE.
 
626
                                                         */
 
627
                                                        s->eweight = s->uweight;
 
628
                                                        if (s->proxy->lbprm.update_server_eweight)
 
629
                                                                s->proxy->lbprm.update_server_eweight(s);
 
630
                                                }
 
631
                                        }
 
632
                                        s->proxy->lbprm.set_server_status_up(s);
458
633
 
459
634
                                        /* check if we can handle some connections queued at the proxy. We
460
635
                                         * will take as many as we can handle.
461
636
                                         */
462
 
                                        for (xferred = 0; !s->maxconn || xferred < srv_dynamic_maxconn(s); xferred++) {
463
 
                                                struct session *sess;
464
 
                                                struct pendconn *p;
465
 
 
466
 
                                                p = pendconn_from_px(s->proxy);
467
 
                                                if (!p)
468
 
                                                        break;
469
 
                                                p->sess->srv = s;
470
 
                                                sess = p->sess;
471
 
                                                pendconn_free(p);
472
 
                                                task_wakeup(sess->task);
473
 
                                        }
 
637
                                        xferred = check_for_pending(s);
474
638
 
475
639
                                        sprintf(trash,
476
640
                                                "%sServer %s/%s is UP. %d active and %d backup servers online.%s"
484
648
                                        send_log(s->proxy, LOG_NOTICE, "%s", trash);
485
649
                                }
486
650
 
487
 
                                s->health = s->rise + s->fall - 1; /* OK now */
 
651
                                if (s->health >= s->rise)
 
652
                                        s->health = s->rise + s->fall - 1; /* OK now */
488
653
                        }
489
654
                        s->curfd = -1; /* no check running anymore */
490
655
                        fd_delete(fd);
491
 
                        while (tv_isle(&t->expire, &now))
492
 
                                tv_ms_add(&t->expire, &t->expire, s->inter);
 
656
 
 
657
                        rv = 0;
 
658
                        if (global.spread_checks > 0) {
 
659
                                rv = s->inter * global.spread_checks / 100;
 
660
                                rv -= (int) (2 * rv * (rand() / (RAND_MAX + 1.0)));
 
661
                                //fprintf(stderr, "process_chk(%p): (%d+/-%d%%) random=%d\n", s, s->inter, global.spread_checks, rv);
 
662
                        }
 
663
                        tv_ms_add(&t->expire, &now, s->inter + rv);
493
664
                        goto new_chk;
494
665
                }
495
 
                else if (s->result < 0 || tv_isle(&t->expire, &now)) {
 
666
                else if ((s->result & SRV_CHK_ERROR) || tv_isle(&t->expire, &now)) {
496
667
                        //fprintf(stderr, "process_chk: 10\n");
497
668
                        /* failure or timeout detected */
498
669
                        if (s->health > s->rise) {
503
674
                                set_server_down(s);
504
675
                        s->curfd = -1;
505
676
                        fd_delete(fd);
506
 
                        while (tv_isle(&t->expire, &now))
507
 
                                tv_ms_add(&t->expire, &t->expire, s->inter);
 
677
 
 
678
                        rv = 0;
 
679
                        if (global.spread_checks > 0) {
 
680
                                rv = s->inter * global.spread_checks / 100;
 
681
                                rv -= (int) (2 * rv * (rand() / (RAND_MAX + 1.0)));
 
682
                                //fprintf(stderr, "process_chk(%p): (%d+/-%d%%) random=%d\n", s, s->inter, global.spread_checks, rv);
 
683
                        }
 
684
                        tv_ms_add(&t->expire, &now, s->inter + rv);
508
685
                        goto new_chk;
509
686
                }
510
 
                /* if result is 0 and there's no timeout, we have to wait again */
 
687
                /* if result is unknown and there's no timeout, we have to wait again */
511
688
        }
512
689
        //fprintf(stderr, "process_chk: 11\n");
513
 
        s->result = 0;
 
690
        s->result = SRV_CHK_UNKNOWN;
514
691
        task_queue(t);  /* restore t to its place in the task list */
515
692
        *next = t->expire;
516
693
 out:
517
694
        return;
518
695
}
519
696
 
 
697
/*
 
698
 * Start health-check.
 
699
 * Returns 0 if OK, -1 if error, and prints the error in this case.
 
700
 */
 
701
int start_checks() {
 
702
 
 
703
        struct proxy *px;
 
704
        struct server *s;
 
705
        struct task *t;
 
706
        int nbchk=0, mininter=0, srvpos=0;
 
707
 
 
708
        /* 1- count the checkers to run simultaneously.
 
709
         * We also determine the minimum interval among all of those which
 
710
         * have an interval larger than SRV_CHK_INTER_THRES. This interval
 
711
         * will be used to spread their start-up date. Those which have
 
712
         * a shorter interval will start independantly and will not dictate
 
713
         * too short an interval for all others.
 
714
         */
 
715
        for (px = proxy; px; px = px->next) {
 
716
                for (s = px->srv; s; s = s->next) {
 
717
                        if (!(s->state & SRV_CHECKED))
 
718
                                continue;
 
719
 
 
720
                        if ((s->inter >= SRV_CHK_INTER_THRES) &&
 
721
                            (!mininter || mininter > s->inter))
 
722
                                mininter = s->inter;
 
723
 
 
724
                        nbchk++;
 
725
                }
 
726
        }
 
727
 
 
728
        if (!nbchk)
 
729
                return 0;
 
730
 
 
731
        srand((unsigned)time(NULL));
 
732
 
 
733
        /*
 
734
         * 2- start them as far as possible from each others. For this, we will
 
735
         * start them after their interval set to the min interval divided by
 
736
         * the number of servers, weighted by the server's position in the list.
 
737
         */
 
738
        for (px = proxy; px; px = px->next) {
 
739
                for (s = px->srv; s; s = s->next) {
 
740
                        if (!(s->state & SRV_CHECKED))
 
741
                                continue;
 
742
 
 
743
                        if ((t = pool_alloc2(pool2_task)) == NULL) {
 
744
                                Alert("Starting [%s:%s] check: out of memory.\n", px->id, s->id);
 
745
                                return -1;
 
746
                        }
 
747
 
 
748
                        t->wq = NULL;
 
749
                        t->qlist.p = NULL;
 
750
                        t->state = TASK_IDLE;
 
751
                        t->process = process_chk;
 
752
                        t->context = s;
 
753
 
 
754
                        /* check this every ms */
 
755
                        tv_ms_add(&t->expire, &now,
 
756
                                  ((mininter && mininter >= s->inter) ? mininter : s->inter) * srvpos / nbchk);
 
757
                        task_queue(t);
 
758
 
 
759
                        srvpos++;
 
760
                }
 
761
        }
 
762
        return 0;
 
763
}
520
764
 
521
765
/*
522
766
 * Local variables: