~ubuntu-branches/ubuntu/saucy/haproxy/saucy-proposed

« back to all changes in this revision

Viewing changes to src/checks.c

  • Committer: Bazaar Package Importer
  • Author(s): Arnaud Cornet
  • Date: 2009-06-26 00:11:01 UTC
  • mfrom: (1.1.6 upstream) (2.1.4 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090626001101-qo261ke2mjh3d8cn
* New Upstream Version (Closes: #534583).
* Add contrib directory in docs

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 * Health-checks functions.
3
3
 *
4
 
 * Copyright 2000-2008 Willy Tarreau <w@1wt.eu>
 
4
 * Copyright 2000-2009 Willy Tarreau <w@1wt.eu>
5
5
 * Copyright 2007-2008 Krzysztof Piotr Oledzki <ole@ans.pl>
6
6
 *
7
7
 * This program is free software; you can redistribute it and/or
30
30
#include <common/time.h>
31
31
 
32
32
#include <types/global.h>
33
 
#include <types/polling.h>
34
 
#include <types/proxy.h>
35
 
#include <types/session.h>
36
33
 
37
34
#include <proto/backend.h>
38
35
#include <proto/buffers.h>
76
73
                        sess->flags &= ~(SN_DIRECT | SN_ASSIGNED | SN_ADDR_SET);
77
74
 
78
75
                        pendconn_free(pc);
79
 
                        task_wakeup(sess->task);
 
76
                        task_wakeup(sess->task, TASK_WOKEN_RES);
80
77
                        xferred++;
81
78
                }
82
79
        }
105
102
                p->sess->srv = s;
106
103
                sess = p->sess;
107
104
                pendconn_free(p);
108
 
                task_wakeup(sess->task);
 
105
                task_wakeup(sess->task, TASK_WOKEN_RES);
109
106
        }
110
107
        return xferred;
111
108
}
164
161
 
165
162
                s->down_trans++;
166
163
 
167
 
                if (s->state && SRV_CHECKED)
 
164
                if (s->state & SRV_CHECKED)
168
165
                        for(srv = s->tracknext; srv; srv = srv->tracknext)
169
166
                                set_server_down(srv);
170
167
        }
224
221
                        " %d sessions requeued, %d total in queue.\n",
225
222
                        s->proxy->srv_act, s->proxy->srv_bck,
226
223
                        (s->proxy->srv_bck && !s->proxy->srv_act) ? " Running on backup." : "",
227
 
                        s->cur_sess, xferred, s->nbpend);
 
224
                        xferred, s->nbpend);
228
225
 
229
226
                Warning("%s", trash);
230
227
                send_log(s->proxy, LOG_NOTICE, "%s", trash);
231
228
 
232
 
                if (s->state && SRV_CHECKED)
 
229
                if (s->state & SRV_CHECKED)
233
230
                        for(srv = s->tracknext; srv; srv = srv->tracknext)
234
231
                                set_server_up(srv);
235
232
        }
280
277
        if (!s->proxy->srv_bck && !s->proxy->srv_act)
281
278
                set_backend_down(s->proxy);
282
279
 
283
 
        if (s->state && SRV_CHECKED)
 
280
        if (s->state & SRV_CHECKED)
284
281
                for(srv = s->tracknext; srv; srv = srv->tracknext)
285
282
                        set_server_disabled(srv);
286
283
}
320
317
        Warning("%s", trash);
321
318
        send_log(s->proxy, LOG_NOTICE, "%s", trash);
322
319
 
323
 
        if (s->state && SRV_CHECKED)
 
320
        if (s->state & SRV_CHECKED)
324
321
                for(srv = s->tracknext; srv; srv = srv->tracknext)
325
322
                        set_server_enabled(srv);
326
323
}
356
353
 
357
354
                        if (s->proxy->options & PR_O_SSL3_CHK) {
358
355
                                /* SSL requires that we put Unix time in the request */
359
 
                                int gmt_time = htonl(now.tv_sec);
 
356
                                int gmt_time = htonl(date.tv_sec);
360
357
                                memcpy(s->proxy->check_req + 11, &gmt_time, 4);
361
358
                        }
362
359
 
367
364
#endif
368
365
                        if (ret == s->proxy->check_len) {
369
366
                                /* we allow up to <timeout.check> if nonzero for a responce */
370
 
                                //fprintf(stderr, "event_srv_chk_w, ms=%lu\n", __tv_to_ms(&s->proxy->timeout.check));
371
 
                                tv_add_ifset(&t->expire, &now, &s->proxy->timeout.check);
372
 
 
 
367
                                if (s->proxy->timeout.check)
 
368
                                        t->expire = tick_add_ifset(now_ms, s->proxy->timeout.check);
373
369
                                EV_FD_SET(fd, DIR_RD);   /* prepare for reading reply */
374
370
                                goto out_nowake;
375
371
                        }
409
405
                }
410
406
        }
411
407
 out_wakeup:
412
 
        task_wakeup(t);
 
408
        task_wakeup(t, TASK_WOKEN_IO);
413
409
 out_nowake:
414
410
        EV_FD_CLR(fd, DIR_WR);   /* nothing more to write */
415
411
        fdtab[fd].ev &= ~FD_POLL_OUT;
517
513
                fdtab[fd].state = FD_STERROR;
518
514
 
519
515
        EV_FD_CLR(fd, DIR_RD);
520
 
        task_wakeup(t);
 
516
        task_wakeup(t, TASK_WOKEN_IO);
521
517
        fdtab[fd].ev &= ~FD_POLL_IN;
522
518
        return 1;
523
519
}
526
522
 * manages a server health-check. Returns
527
523
 * the time the task accepts to wait, or TIME_ETERNITY for infinity.
528
524
 */
529
 
void process_chk(struct task *t, struct timeval *next)
 
525
struct task *process_chk(struct task *t)
530
526
{
531
 
        __label__ new_chk, out;
 
527
        int attempts = 0;
532
528
        struct server *s = t->context;
533
529
        struct sockaddr_in sa;
534
530
        int fd;
537
533
        //fprintf(stderr, "process_chk: task=%p\n", t);
538
534
 
539
535
 new_chk:
 
536
        if (attempts++ > 0) {
 
537
                /* we always fail to create a server, let's stop insisting... */
 
538
                while (tick_is_expired(t->expire, now_ms))
 
539
                        t->expire = tick_add(t->expire, MS_TO_TICKS(s->inter));
 
540
                return t;
 
541
        }
540
542
        fd = s->curfd;
541
543
        if (fd < 0) {   /* no check currently running */
542
544
                //fprintf(stderr, "process_chk: 2\n");
543
 
                if (!tv_isle(&t->expire, &now)) { /* not good time yet */
544
 
                        task_queue(t);  /* restore t to its place in the task list */
545
 
                        *next = t->expire;
546
 
                        goto out;
547
 
                }
 
545
                if (!tick_is_expired(t->expire, now_ms)) /* woke up too early */
 
546
                        return t;
548
547
 
549
548
                /* we don't send any health-checks when the proxy is stopped or when
550
549
                 * the server should not be checked.
551
550
                 */
552
551
                if (!(s->state & SRV_CHECKED) || s->proxy->state == PR_STSTOPPED) {
553
 
                        while (tv_isle(&t->expire, &now))
554
 
                                tv_ms_add(&t->expire, &t->expire, s->inter);
555
 
                        task_queue(t);  /* restore t to its place in the task list */
556
 
                        *next = t->expire;
557
 
                        goto out;
 
552
                        while (tick_is_expired(t->expire, now_ms))
 
553
                                t->expire = tick_add(t->expire, MS_TO_TICKS(s->inter));
 
554
                        return t;
558
555
                }
559
556
 
560
557
                /* we'll initiate a new check */
594
591
                                                flags  = 3;
595
592
                                        }
596
593
#endif
 
594
#ifdef SO_BINDTODEVICE
 
595
                                        /* Note: this might fail if not CAP_NET_RAW */
 
596
                                        if (s->iface_name)
 
597
                                                setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE,
 
598
                                                           s->iface_name, s->iface_len + 1);
 
599
#endif
597
600
                                        ret = tcpv4_bind_socket(fd, flags, &s->source_addr, remote);
598
601
                                        if (ret) {
599
602
                                                s->result |= SRV_CHK_ERROR;
619
622
                                                flags  = 3;
620
623
                                        }
621
624
#endif
 
625
#ifdef SO_BINDTODEVICE
 
626
                                        /* Note: this might fail if not CAP_NET_RAW */
 
627
                                        if (s->proxy->iface_name)
 
628
                                                setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE,
 
629
                                                           s->proxy->iface_name, s->proxy->iface_len + 1);
 
630
#endif
622
631
                                        ret = tcpv4_bind_socket(fd, flags, &s->proxy->source_addr, remote);
623
632
                                        if (ret) {
624
633
                                                s->result |= SRV_CHK_ERROR;
637
646
 
638
647
                                if (s->result == SRV_CHK_UNKNOWN) {
639
648
                                        if ((connect(fd, (struct sockaddr *)&sa, sizeof(sa)) != -1) || (errno == EINPROGRESS)) {
640
 
                                                struct timeval tv_con;
641
 
 
642
649
                                                /* OK, connection in progress or established */
643
650
                        
644
651
                                                //fprintf(stderr, "process_chk: 4\n");
662
669
                                                 * to establish but only when timeout.check is set
663
670
                                                 * as it may be to short for a full check otherwise
664
671
                                                 */
665
 
                                                tv_ms_add(&t->expire, &now, s->inter);
 
672
                                                t->expire = tick_add(now_ms, MS_TO_TICKS(s->inter));
666
673
 
667
 
                                                if (tv_isset(&s->proxy->timeout.check) && tv_isset(&s->proxy->timeout.connect)) {
668
 
                                                        tv_add(&tv_con, &now, &s->proxy->timeout.connect);
669
 
                                                        tv_bound(&t->expire, &tv_con);
 
674
                                                if (s->proxy->timeout.check && s->proxy->timeout.connect) {
 
675
                                                        int t_con = tick_add(now_ms, s->proxy->timeout.connect);
 
676
                                                        t->expire = tick_first(t->expire, t_con);
670
677
                                                }
671
 
 
672
 
                                                task_queue(t);  /* restore t to its place in the task list */
673
 
                                                *next = t->expire;
674
 
                                                return;
 
678
                                                return t;
675
679
                                        }
676
680
                                        else if (errno != EALREADY && errno != EISCONN && errno != EAGAIN) {
677
681
                                                s->result |= SRV_CHK_ERROR;    /* a real error */
683
687
 
684
688
                if (s->result == SRV_CHK_UNKNOWN) { /* nothing done */
685
689
                        //fprintf(stderr, "process_chk: 6\n");
686
 
                        while (tv_isle(&t->expire, &now))
687
 
                                tv_ms_add(&t->expire, &t->expire, s->inter);
 
690
                        while (tick_is_expired(t->expire, now_ms))
 
691
                                t->expire = tick_add(t->expire, MS_TO_TICKS(s->inter));
688
692
                        goto new_chk; /* may be we should initialize a new check */
689
693
                }
690
694
 
701
705
                 * to establish but only when timeout.check is set
702
706
                 * as it may be to short for a full check otherwise
703
707
                 */
704
 
                while (tv_isle(&t->expire, &now)) {
705
 
                        struct timeval tv_con;
706
 
 
707
 
                        tv_add(&tv_con, &t->expire, &s->proxy->timeout.connect);
708
 
                        tv_ms_add(&t->expire, &t->expire, s->inter);
709
 
 
710
 
                        if (tv_isset(&s->proxy->timeout.check))
711
 
                                tv_bound(&t->expire, &tv_con);
 
708
                while (tick_is_expired(t->expire, now_ms)) {
 
709
                        int t_con;
 
710
 
 
711
                        t_con = tick_add(t->expire, s->proxy->timeout.connect);
 
712
                        t->expire = tick_add(t->expire, MS_TO_TICKS(s->inter));
 
713
 
 
714
                        if (s->proxy->timeout.check)
 
715
                                t->expire = tick_first(t->expire, t_con);
712
716
                }
713
717
                goto new_chk;
714
718
        }
763
767
                                rv -= (int) (2 * rv * (rand() / (RAND_MAX + 1.0)));
764
768
                                //fprintf(stderr, "process_chk(%p): (%d+/-%d%%) random=%d\n", s, srv_getinter(s), global.spread_checks, rv);
765
769
                        }
766
 
                        tv_ms_add(&t->expire, &now, srv_getinter(s) + rv);
 
770
                        t->expire = tick_add(now_ms, MS_TO_TICKS(srv_getinter(s) + rv));
767
771
                        goto new_chk;
768
772
                }
769
 
                else if ((s->result & SRV_CHK_ERROR) || tv_isle(&t->expire, &now)) {
 
773
                else if ((s->result & SRV_CHK_ERROR) || tick_is_expired(t->expire, now_ms)) {
770
774
                        //fprintf(stderr, "process_chk: 10\n");
771
775
                        /* failure or timeout detected */
772
776
                        if (s->health > s->rise) {
784
788
                                rv -= (int) (2 * rv * (rand() / (RAND_MAX + 1.0)));
785
789
                                //fprintf(stderr, "process_chk(%p): (%d+/-%d%%) random=%d\n", s, srv_getinter(s), global.spread_checks, rv);
786
790
                        }
787
 
                        tv_ms_add(&t->expire, &now, srv_getinter(s) + rv);
 
791
                        t->expire = tick_add(now_ms, MS_TO_TICKS(srv_getinter(s) + rv));
788
792
                        goto new_chk;
789
793
                }
790
794
                /* if result is unknown and there's no timeout, we have to wait again */
791
795
        }
792
796
        //fprintf(stderr, "process_chk: 11\n");
793
797
        s->result = SRV_CHK_UNKNOWN;
794
 
        task_queue(t);  /* restore t to its place in the task list */
795
 
        *next = t->expire;
796
 
 out:
797
 
        return;
 
798
        return t;
798
799
}
799
800
 
800
801
/*
843
844
                        if (!(s->state & SRV_CHECKED))
844
845
                                continue;
845
846
 
846
 
                        if ((t = pool_alloc2(pool2_task)) == NULL) {
 
847
                        if ((t = task_new()) == NULL) {
847
848
                                Alert("Starting [%s:%s] check: out of memory.\n", px->id, s->id);
848
849
                                return -1;
849
850
                        }
850
851
 
851
 
                        t->wq = NULL;
852
 
                        t->qlist.p = NULL;
853
 
                        t->state = TASK_IDLE;
 
852
                        s->check = t;
854
853
                        t->process = process_chk;
855
854
                        t->context = s;
856
855
 
857
856
                        /* check this every ms */
858
 
                        tv_ms_add(&t->expire, &now,
859
 
                                  ((mininter && mininter >= srv_getinter(s)) ? mininter : srv_getinter(s)) * srvpos / nbchk);
 
857
                        t->expire = tick_add(now_ms,
 
858
                                             MS_TO_TICKS(((mininter && mininter >= srv_getinter(s)) ?
 
859
                                                          mininter : srv_getinter(s)) * srvpos / nbchk));
860
860
                        task_queue(t);
861
861
 
862
862
                        srvpos++;