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