varnish-cache/bin/varnishd/waiter/cache_waiter.c
0
/*-
1
 * Copyright (c) 2006 Verdens Gang AS
2
 * Copyright (c) 2006-2015 Varnish Software AS
3
 * All rights reserved.
4
 *
5
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
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
32
#include "config.h"
33
34
#include "cache/cache_varnishd.h"
35
36
#include <stdlib.h>
37
38
#include "vbh.h"
39
40
#include "waiter/waiter.h"
41
#include "waiter/waiter_priv.h"
42
#include "waiter/mgt_waiter.h"
43
44
#include "VSC_waiter.h"
45
46
static int v_matchproto_(vbh_cmp_t)
47 8104
waited_cmp(void *priv, const void *a, const void *b)
48
{
49
        const struct waiter *ww;
50
        const struct waited *aa, *bb;
51
52 8104
        CAST_OBJ_NOTNULL(ww, priv, WAITER_MAGIC);
53 8104
        CAST_OBJ_NOTNULL(aa, a, WAITED_MAGIC);
54 8104
        CAST_OBJ_NOTNULL(bb, b, WAITED_MAGIC);
55
56 8104
        return (Wait_When(aa) < Wait_When(bb));
57
}
58
59
static void v_matchproto_(vbh_update_t)
60 164934
waited_update(void *priv, void *p, unsigned u)
61
{
62
        struct waited *pp;
63
64 164934
        (void)priv;
65 164934
        CAST_OBJ_NOTNULL(pp, p, WAITED_MAGIC);
66 164934
        pp->idx = u;
67 164934
}
68
69
/**********************************************************************/
70
71
void
72 76166
Wait_Call(const struct waiter *w, struct waited *wp,
73
    enum wait_event ev, double now)
74
{
75 76166
        CHECK_OBJ_NOTNULL(w, WAITER_MAGIC);
76 76166
        CHECK_OBJ_NOTNULL(wp, WAITED_MAGIC);
77 76166
        AN(wp->func);
78 76166
        assert(wp->idx == VBH_NOIDX);
79 76166
        AN(w->vsc);
80
81 76166
        switch (ev) {
82
        case WAITER_REMCLOSE:
83 38496
                w->vsc->remclose++;
84 38496
                break;
85
        case WAITER_TIMEOUT:
86 520
                w->vsc->timeout++;
87 520
                break;
88
        case WAITER_ACTION:
89 37150
                w->vsc->action++;
90 37150
                break;
91
        default:
92 0
                break;
93
        }
94
95 76166
        wp->func(wp, ev, now);
96 76166
}
97
98
/**********************************************************************/
99
100
void
101 77241
Wait_HeapInsert(const struct waiter *w, struct waited *wp)
102
{
103 77241
        CHECK_OBJ_NOTNULL(w, WAITER_MAGIC);
104 77241
        CHECK_OBJ_NOTNULL(wp, WAITED_MAGIC);
105 77241
        assert(wp->idx == VBH_NOIDX);
106 77241
        AN(w->vsc);
107 77241
        w->vsc->conns++;
108 77241
        VBH_insert(w->heap, wp);
109 77241
}
110
111
/*
112
 * XXX: wp is const because otherwise FlexeLint complains.  However, *wp
113
 * XXX: will actually change as a result of calling this function, via
114
 * XXX: the pointer stored in the bin-heap.  I can see how this const
115
 * XXX: could maybe confuse a compilers optimizer, but I do not expect
116
 * XXX: any harm to come from it.  Caveat Emptor.
117
 */
118
119
int
120 76165
Wait_HeapDelete(const struct waiter *w, const struct waited *wp)
121
{
122 76165
        CHECK_OBJ_NOTNULL(w, WAITER_MAGIC);
123 76165
        CHECK_OBJ_NOTNULL(wp, WAITED_MAGIC);
124 76165
        if (wp->idx == VBH_NOIDX)
125 0
                return (0);
126 76165
        AN(w->vsc);
127 76165
        w->vsc->conns--;
128 76165
        VBH_delete(w->heap, wp->idx);
129 76165
        return (1);
130 76165
}
131
132
double
133 197113
Wait_HeapDue(const struct waiter *w, struct waited **wpp)
134
{
135
        struct waited *wp;
136
137 197113
        wp = VBH_root(w->heap);
138 197113
        CHECK_OBJ_ORNULL(wp, WAITED_MAGIC);
139 197113
        if (wp == NULL) {
140 148540
                if (wpp != NULL)
141 148540
                        *wpp = NULL;
142 148540
                return (0);
143
        }
144 48573
        if (wpp != NULL)
145 46042
                *wpp = wp;
146 48573
        return (Wait_When(wp));
147 197113
}
148
149
/**********************************************************************/
150
151
int
152 77239
Wait_Enter(const struct waiter *w, struct waited *wp)
153
{
154
155 77239
        CHECK_OBJ_NOTNULL(w, WAITER_MAGIC);
156 77239
        CHECK_OBJ_NOTNULL(wp, WAITED_MAGIC);
157 77239
        assert(wp->fd > 0);                     // stdin never comes here
158 77239
        AN(wp->func);
159 77239
        wp->idx = VBH_NOIDX;
160 77239
        return (w->impl->enter(w->priv, wp));
161
}
162
163
/**********************************************************************/
164
165
const char *
166 511
Waiter_GetName(void)
167
{
168
169 511
        if (waiter != NULL)
170 511
                return (waiter->name);
171
        else
172 0
                return ("(No Waiter?)");
173 511
}
174
175
struct waiter *
176 73980
Waiter_New(const char *name)
177
{
178
        struct waiter *w;
179
180 73980
        AN(waiter);
181 73980
        AN(waiter->name);
182 73980
        AN(waiter->init);
183 73980
        AN(waiter->enter);
184 73980
        AN(waiter->fini);
185
186 73980
        w = calloc(1, sizeof (struct waiter) + waiter->size);
187 73980
        AN(w);
188 73980
        INIT_OBJ(w, WAITER_MAGIC);
189 73980
        w->priv = (void*)(w + 1);
190 73980
        w->impl = waiter;
191 73980
        VTAILQ_INIT(&w->waithead);
192 73980
        w->heap = VBH_new(w, waited_cmp, waited_update);
193
194 73980
        AZ(w->vsc);
195 73980
        w->vsc = VSC_waiter_New(NULL, NULL, "%s", name);
196 73980
        AN(w->vsc);
197
198 73980
        waiter->init(w);
199
200 73980
        return (w);
201
}
202
203
void
204 80
Waiter_Destroy(struct waiter **wp)
205
{
206
        struct waiter *w;
207
208 80
        TAKE_OBJ_NOTNULL(w, wp, WAITER_MAGIC);
209
210 80
        AZ(VBH_root(w->heap));
211 80
        AN(w->impl->fini);
212 80
        w->impl->fini(w);
213 80
        FREE_OBJ(w);
214 80
}