varnish-cache/vmod/vmod_directors_fall_back.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
 * SPDX-License-Identifier: BSD-2-Clause
8
 *
9
 * Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions
11
 * are met:
12
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
14
 * 2. Redistributions in binary form must reproduce the above copyright
15
 *    notice, this list of conditions and the following disclaimer in the
16
 *    documentation and/or other materials provided with the distribution.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
22
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28
 * SUCH DAMAGE.
29
 */
30
31
#include "config.h"
32
33
#include <stdlib.h>
34
#include <string.h>
35
36
#include "cache/cache.h"
37
38
#include "vcc_directors_if.h"
39
40
#include "vmod_directors.h"
41
#include "vsb.h"
42
#include "vbm.h"
43
44
struct vmod_directors_fallback {
45
        unsigned                                magic;
46
#define VMOD_DIRECTORS_FALLBACK_MAGIC           0xad4e26ba
47
        struct vdir                             *vd;
48
        VCL_BOOL                                st;
49
        unsigned                                cur;
50
};
51
52
static VCL_BOOL v_matchproto_(vdi_healthy)
53 84
vmod_fallback_healthy(VRT_CTX, VCL_BACKEND dir, VCL_TIME *changed)
54
{
55
        struct vmod_directors_fallback *fb;
56
57 84
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
58 84
        CHECK_OBJ_NOTNULL(dir, DIRECTOR_MAGIC);
59 84
        CAST_OBJ_NOTNULL(fb, dir->priv, VMOD_DIRECTORS_FALLBACK_MAGIC);
60 84
        return (vdir_any_healthy(ctx, fb->vd, changed));
61
}
62
63
static void v_matchproto_(vdi_list_f)
64 273
vmod_fallback_list(VRT_CTX, VCL_BACKEND dir, struct vsb *vsb, int pflag,
65
    int jflag)
66
{
67
        struct vmod_directors_fallback *fb;
68
        struct vdir *vd;
69
        VCL_BACKEND be;
70
        VCL_BOOL h;
71
        unsigned u, nh;
72
73 273
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
74 273
        CHECK_OBJ_NOTNULL(dir, DIRECTOR_MAGIC);
75 273
        CAST_OBJ_NOTNULL(fb, dir->priv, VMOD_DIRECTORS_FALLBACK_MAGIC);
76 273
        CAST_OBJ_NOTNULL(vd, fb->vd, VDIR_MAGIC);
77
78 273
        if (pflag) {
79 42
                if (jflag) {
80 21
                        VSB_cat(vsb, "{\n");
81 21
                        VSB_indent(vsb, 2);
82 42
                        VSB_printf(vsb, "\"sticky\": %s,\n",
83 21
                            fb->st ? "true" : "false");
84 21
                        VSB_cat(vsb, "\"backends\": {\n");
85 21
                        VSB_indent(vsb, 2);
86 21
                } else {
87 21
                        VSB_cat(vsb, "\n\n\tBackend\tCurrent\tHealth\n");
88
                }
89 42
        }
90
91 273
        vdir_rdlock(vd);
92 273
        vdir_update_health(ctx, vd);
93 441
        for (u = 0; pflag && u < vd->n_backend; u++) {
94 168
                be = vd->backend[u];
95 168
                CHECK_OBJ_NOTNULL(be, DIRECTOR_MAGIC);
96
97 168
                h = vbit_test(vd->healthy, u);
98
99 168
                if (jflag) {
100 84
                        if (u)
101 63
                                VSB_cat(vsb, ",\n");
102 84
                        VSB_printf(vsb, "\"%s\": {\n", be->vcl_name);
103 84
                        VSB_indent(vsb, 2);
104
105 84
                        if (fb->cur == u)
106 21
                                VSB_cat(vsb, "\"current\": true,\n");
107
                        else
108 63
                                VSB_cat(vsb, "\"current\": false,\n");
109
110 84
                        if (h)
111 63
                                VSB_cat(vsb, "\"health\": \"healthy\"\n");
112
                        else
113 21
                                VSB_cat(vsb, "\"health\": \"sick\"\n");
114
115 84
                        VSB_indent(vsb, -2);
116 84
                        VSB_cat(vsb, "}");
117 84
                } else {
118 84
                        VSB_cat(vsb, "\t");
119 84
                        VSB_cat(vsb, be->vcl_name);
120 84
                        if (fb->cur == u)
121 21
                                VSB_cat(vsb, "\t*\t");
122
                        else
123 63
                                VSB_cat(vsb, "\t\t");
124 84
                        VSB_cat(vsb, h ? "healthy" : "sick");
125 84
                        VSB_cat(vsb, "\n");
126
                }
127 168
        }
128 273
        nh = vd->n_healthy;
129 273
        u = vd->n_backend;
130 273
        vdir_unlock(vd);
131
132 273
        if (jflag && (pflag)) {
133 21
                VSB_cat(vsb, "\n");
134 21
                VSB_indent(vsb, -2);
135 21
                VSB_cat(vsb, "}\n");
136 21
                VSB_indent(vsb, -2);
137 21
                VSB_cat(vsb, "},\n");
138 21
        }
139
140 273
        if (pflag)
141 42
                return;
142
143 231
        if (jflag)
144 126
                VSB_printf(vsb, "[%u, %u, \"%s\"]", nh, u,
145 63
                    nh ? "healthy" : "sick");
146
        else
147 168
                VSB_printf(vsb, "%u/%u\t%s", nh, u, nh ? "healthy" : "sick");
148 273
}
149
150
static VCL_BACKEND v_matchproto_(vdi_resolve_f)
151 483
vmod_fallback_resolve(VRT_CTX, VCL_BACKEND dir)
152
{
153
        struct vmod_directors_fallback *fb;
154
        unsigned u;
155 483
        VCL_BACKEND be = NULL;
156
157 483
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
158 483
        CHECK_OBJ_NOTNULL(dir, DIRECTOR_MAGIC);
159 483
        CAST_OBJ_NOTNULL(fb, dir->priv, VMOD_DIRECTORS_FALLBACK_MAGIC);
160
161 483
        vdir_wrlock(fb->vd);
162 483
        if (!fb->st)
163 294
                fb->cur = 0;
164 777
        for (u = 0; u < fb->vd->n_backend; u++) {
165 756
                be = fb->vd->backend[fb->cur];
166 756
                CHECK_OBJ_NOTNULL(be, DIRECTOR_MAGIC);
167 756
                if (VRT_Healthy(ctx, be, NULL))
168 462
                        break;
169 294
                if (++fb->cur == fb->vd->n_backend)
170 42
                        fb->cur = 0;
171 294
        }
172 483
        vdir_unlock(fb->vd);
173 483
        if (u == fb->vd->n_backend)
174 21
                be = NULL;
175 483
        return (be);
176
}
177
178
static void v_matchproto_(vdi_destroy_f)
179 21
vmod_fallback_destroy(VCL_BACKEND dir)
180
{
181
        struct vmod_directors_fallback *fallback;
182
183 21
        CAST_OBJ_NOTNULL(fallback, dir->priv, VMOD_DIRECTORS_FALLBACK_MAGIC);
184 21
        vdir_delete(&fallback->vd);
185 21
        FREE_OBJ(fallback);
186 21
}
187
188
static const struct vdi_methods vmod_fallback_methods[1] = {{
189
        .magic =                VDI_METHODS_MAGIC,
190
        .type =                 "fallback",
191
        .healthy =              vmod_fallback_healthy,
192
        .resolve =              vmod_fallback_resolve,
193
        .destroy =              vmod_fallback_destroy,
194
        .list =                 vmod_fallback_list
195
}};
196
197
198
VCL_VOID v_matchproto_()
199 105
vmod_fallback__init(VRT_CTX,
200
    struct vmod_directors_fallback **fbp, const char *vcl_name, VCL_BOOL sticky)
201
{
202
        struct vmod_directors_fallback *fb;
203
204 105
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
205 105
        AN(fbp);
206 105
        AZ(*fbp);
207 105
        ALLOC_OBJ(fb, VMOD_DIRECTORS_FALLBACK_MAGIC);
208 105
        AN(fb);
209 105
        *fbp = fb;
210 105
        vdir_new(ctx, &fb->vd, vcl_name, vmod_fallback_methods, fb);
211 105
        fb->st = sticky;
212 105
}
213
214
VCL_VOID v_matchproto_()
215 21
vmod_fallback__fini(struct vmod_directors_fallback **fbp)
216
{
217
        struct vmod_directors_fallback *fb;
218
219 21
        TAKE_OBJ_NOTNULL(fb, fbp, VMOD_DIRECTORS_FALLBACK_MAGIC);
220 21
        VRT_DelDirector(&fb->vd->dir);
221 21
}
222
223
VCL_VOID v_matchproto_()
224 336
vmod_fallback_add_backend(VRT_CTX,
225
    struct vmod_directors_fallback *fb, VCL_BACKEND be)
226
{
227
228 336
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
229 336
        CHECK_OBJ_NOTNULL(fb, VMOD_DIRECTORS_FALLBACK_MAGIC);
230 336
        vdir_add_backend(ctx, fb->vd, be, 0.0);
231 336
}
232
233
VCL_VOID v_matchproto_()
234 84
vmod_fallback_remove_backend(VRT_CTX,
235
    struct vmod_directors_fallback *fb, VCL_BACKEND be)
236
{
237 84
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
238 84
        CHECK_OBJ_NOTNULL(fb, VMOD_DIRECTORS_FALLBACK_MAGIC);
239 84
        vdir_remove_backend(ctx, fb->vd, be, &fb->cur);
240 84
}
241
242
VCL_BACKEND v_matchproto_()
243 567
vmod_fallback_backend(VRT_CTX,
244
    struct vmod_directors_fallback *fb)
245
{
246 567
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
247 567
        CHECK_OBJ_NOTNULL(fb, VMOD_DIRECTORS_FALLBACK_MAGIC);
248 567
        return (fb->vd->dir);
249
}