varnish-cache/lib/libvmod_directors/round_robin.c
1
/*-
2
 * Copyright (c) 2013-2015 Varnish Software AS
3
 * All rights reserved.
4
 *
5
 * Author: Poul-Henning Kamp <phk@FreeBSD.org>
6
 *
7
 * Redistribution and use in source and binary forms, with or without
8
 * modification, are permitted provided that the following conditions
9
 * are met:
10
 * 1. Redistributions of source code must retain the above copyright
11
 *    notice, this list of conditions and the following disclaimer.
12
 * 2. Redistributions in binary form must reproduce the above copyright
13
 *    notice, this list of conditions and the following disclaimer in the
14
 *    documentation and/or other materials provided with the distribution.
15
 *
16
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
20
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26
 * SUCH DAMAGE.
27
 */
28
29
#include "config.h"
30
31
#include <stdlib.h>
32
#include <string.h>
33
34
#include "cache/cache.h"
35
#include "cache/cache_director.h"
36
37
#include "vcc_if.h"
38
39
#include "vdir.h"
40
41
struct vmod_directors_round_robin {
42
        unsigned                                magic;
43
#define VMOD_DIRECTORS_ROUND_ROBIN_MAGIC        0xa80970cf
44
        struct vdir                             *vd;
45
        unsigned                                nxt;
46
};
47
48
static unsigned v_matchproto_(vdi_healthy)
49 20
vmod_rr_healthy(const struct director *dir, const struct busyobj *bo,
50
    double *changed)
51
{
52
        struct vmod_directors_round_robin *rr;
53
54 20
        CAST_OBJ_NOTNULL(rr, dir->priv, VMOD_DIRECTORS_ROUND_ROBIN_MAGIC);
55 20
        return (vdir_any_healthy(rr->vd, bo, changed));
56
}
57
58
static const struct director * v_matchproto_(vdi_resolve_f)
59 30
vmod_rr_resolve(const struct director *dir, struct worker *wrk,
60
    struct busyobj *bo)
61
{
62
        struct vmod_directors_round_robin *rr;
63
        unsigned u;
64 30
        VCL_BACKEND be = NULL;
65
        unsigned nxt;
66
67 30
        CHECK_OBJ_NOTNULL(dir, DIRECTOR_MAGIC);
68 30
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
69 30
        CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
70 30
        CAST_OBJ_NOTNULL(rr, dir->priv, VMOD_DIRECTORS_ROUND_ROBIN_MAGIC);
71 30
        vdir_rdlock(rr->vd);
72 32
        for (u = 0; u < rr->vd->n_backend; u++) {
73 32
                nxt = rr->nxt % rr->vd->n_backend;
74 32
                rr->nxt = nxt + 1;
75 32
                be = rr->vd->backend[nxt];
76 32
                CHECK_OBJ_NOTNULL(be, DIRECTOR_MAGIC);
77 32
                if (be->healthy(be, bo, NULL))
78 30
                        break;
79
        }
80 30
        vdir_unlock(rr->vd);
81 30
        if (u == rr->vd->n_backend)
82 0
                be = NULL;
83 30
        return (be);
84
}
85
86
VCL_VOID v_matchproto_()
87 9
vmod_round_robin__init(VRT_CTX,
88
    struct vmod_directors_round_robin **rrp, const char *vcl_name)
89
{
90
        struct vmod_directors_round_robin *rr;
91
92 9
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
93 9
        AN(rrp);
94 9
        AZ(*rrp);
95 9
        ALLOC_OBJ(rr, VMOD_DIRECTORS_ROUND_ROBIN_MAGIC);
96 9
        AN(rr);
97 9
        *rrp = rr;
98 9
        vdir_new(&rr->vd, "round-robin", vcl_name, vmod_rr_healthy,
99
            vmod_rr_resolve, rr);
100 9
}
101
102
VCL_VOID v_matchproto_()
103 1
vmod_round_robin__fini(struct vmod_directors_round_robin **rrp)
104
{
105
        struct vmod_directors_round_robin *rr;
106
107 1
        rr = *rrp;
108 1
        *rrp = NULL;
109 1
        CHECK_OBJ_NOTNULL(rr, VMOD_DIRECTORS_ROUND_ROBIN_MAGIC);
110 1
        vdir_delete(&rr->vd);
111 1
        FREE_OBJ(rr);
112 1
}
113
114
VCL_VOID v_matchproto_()
115 17
vmod_round_robin_add_backend(VRT_CTX,
116
    struct vmod_directors_round_robin *rr, VCL_BACKEND be)
117
{
118
119 17
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
120 17
        CHECK_OBJ_NOTNULL(rr, VMOD_DIRECTORS_ROUND_ROBIN_MAGIC);
121 17
        vdir_add_backend(ctx, rr->vd, be, 0.0);
122 17
}
123
124
VCL_VOID v_matchproto_()
125 3
vmod_round_robin_remove_backend(VRT_CTX,
126
    struct vmod_directors_round_robin *rr, VCL_BACKEND be)
127
{
128 3
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
129 3
        CHECK_OBJ_NOTNULL(rr, VMOD_DIRECTORS_ROUND_ROBIN_MAGIC);
130 3
        vdir_remove_backend(ctx, rr->vd, be, NULL);
131 3
}
132
133
VCL_BACKEND v_matchproto_()
134 19
vmod_round_robin_backend(VRT_CTX,
135
    struct vmod_directors_round_robin *rr)
136
{
137
138 19
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
139 19
        CHECK_OBJ_NOTNULL(rr, VMOD_DIRECTORS_ROUND_ROBIN_MAGIC);
140 19
        return (rr->vd->dir);
141
}