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