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 8198
waited_cmp(void *priv, const void *a, const void *b)
48
{
49
        const struct waiter *ww;
50
        const struct waited *aa, *bb;
51
52 8198
        CAST_OBJ_NOTNULL(ww, priv, WAITER_MAGIC);
53 8198
        CAST_OBJ_NOTNULL(aa, a, WAITED_MAGIC);
54 8198
        CAST_OBJ_NOTNULL(bb, b, WAITED_MAGIC);
55
56 8198
        return (Wait_When(aa) < Wait_When(bb));
57
}
58
59
static void v_matchproto_(vbh_update_t)
60 161309
waited_update(void *priv, void *p, unsigned u)
61
{
62
        struct waited *pp;
63
64 161309
        (void)priv;
65 161309
        CAST_OBJ_NOTNULL(pp, p, WAITED_MAGIC);
66 161309
        pp->idx = u;
67 161309
}
68
69
/**********************************************************************/
70
71
void
72 74485
Wait_Call(const struct waiter *w, struct waited *wp,
73
    enum wait_event ev, double now)
74
{
75 74485
        CHECK_OBJ_NOTNULL(w, WAITER_MAGIC);
76 74485
        CHECK_OBJ_NOTNULL(wp, WAITED_MAGIC);
77 74485
        AN(wp->func);
78 74485
        assert(wp->idx == VBH_NOIDX);
79 74485
        AN(w->vsc);
80
81 74485
        switch (ev) {
82
        case WAITER_REMCLOSE:
83 37811
                w->vsc->remclose++;
84 37811
                break;
85
        case WAITER_TIMEOUT:
86 480
                w->vsc->timeout++;
87 480
                break;
88
        case WAITER_ACTION:
89 36194
                w->vsc->action++;
90 36194
                break;
91
        default:
92 0
                break;
93
        }
94
95 74485
        wp->func(wp, ev, now);
96 74485
}
97
98
/**********************************************************************/
99
100
void
101 75527
Wait_HeapInsert(const struct waiter *w, struct waited *wp)
102
{
103 75527
        CHECK_OBJ_NOTNULL(w, WAITER_MAGIC);
104 75527
        CHECK_OBJ_NOTNULL(wp, WAITED_MAGIC);
105 75527
        assert(wp->idx == VBH_NOIDX);
106 75527
        AN(w->vsc);
107 75527
        w->vsc->conns++;
108 75527
        VBH_insert(w->heap, wp);
109 75527
}
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 74485
Wait_HeapDelete(const struct waiter *w, const struct waited *wp)
121
{
122 74485
        CHECK_OBJ_NOTNULL(w, WAITER_MAGIC);
123 74485
        CHECK_OBJ_NOTNULL(wp, WAITED_MAGIC);
124 74485
        if (wp->idx == VBH_NOIDX)
125 0
                return (0);
126 74485
        AN(w->vsc);
127 74485
        w->vsc->conns--;
128 74485
        VBH_delete(w->heap, wp->idx);
129 74485
        return (1);
130 74485
}
131
132
double
133 192849
Wait_HeapDue(const struct waiter *w, struct waited **wpp)
134
{
135
        struct waited *wp;
136
137 192849
        wp = VBH_root(w->heap);
138 192849
        CHECK_OBJ_ORNULL(wp, WAITED_MAGIC);
139 192849
        if (wp == NULL) {
140 145379
                if (wpp != NULL)
141 145379
                        *wpp = NULL;
142 145379
                return (0);
143
        }
144 47470
        if (wpp != NULL)
145 44809
                *wpp = wp;
146 47470
        return (Wait_When(wp));
147 192849
}
148
149
/**********************************************************************/
150
151
int
152 75526
Wait_Enter(const struct waiter *w, struct waited *wp)
153
{
154
155 75526
        CHECK_OBJ_NOTNULL(w, WAITER_MAGIC);
156 75526
        CHECK_OBJ_NOTNULL(wp, WAITED_MAGIC);
157 75526
        assert(wp->fd > 0);                     // stdin never comes here
158 75526
        AN(wp->func);
159 75526
        wp->idx = VBH_NOIDX;
160 75526
        return (w->impl->enter(w->priv, wp));
161
}
162
163
/**********************************************************************/
164
165
const char *
166 516
Waiter_GetName(void)
167
{
168
169 516
        if (waiter != NULL)
170 516
                return (waiter->name);
171
        else
172 0
                return ("(No Waiter?)");
173 516
}
174
175
struct waiter *
176 72551
Waiter_New(const char *name)
177
{
178
        struct waiter *w;
179
180 72551
        AN(waiter);
181 72551
        AN(waiter->name);
182 72551
        AN(waiter->init);
183 72551
        AN(waiter->enter);
184 72551
        AN(waiter->fini);
185
186 72551
        w = calloc(1, sizeof (struct waiter) + waiter->size);
187 72551
        AN(w);
188 72551
        INIT_OBJ(w, WAITER_MAGIC);
189 72551
        w->priv = (void*)(w + 1);
190 72551
        w->impl = waiter;
191 72551
        VTAILQ_INIT(&w->waithead);
192 72551
        w->heap = VBH_new(w, waited_cmp, waited_update);
193
194 72551
        AZ(w->vsc);
195 72551
        w->vsc = VSC_waiter_New(NULL, NULL, "%s", name);
196 72551
        AN(w->vsc);
197
198 72551
        waiter->init(w);
199
200 72551
        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
}