vinyl-cache/bin/vinyld/cache/cache_filter.h
0
/*-
1
 * Copyright (c) 2013-2015 Varnish Software AS
2
 * All rights reserved.
3
 *
4
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
5
 *
6
 * SPDX-License-Identifier: BSD-2-Clause
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
21
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
 * SUCH DAMAGE.
28
 *
29
 */
30
31
struct req;
32
struct vfp_entry;
33
struct vfp_ctx;
34
struct vdp_ctx;
35
struct vdp_entry;
36
37
/* Fetch processors --------------------------------------------------*/
38
39
#define VFP_DEBUG(ctx, fmt, ...)                                        \
40
        do {                                                            \
41
                if (!DO_DEBUG(DBG_PROCESSORS))                          \
42
                        break;                                          \
43
                VSLb((ctx)->wrk->vsl, SLT_Debug, "VFP:%s:%d: " fmt,     \
44
                    __func__, __LINE__, __VA_ARGS__);                   \
45
        } while (0)
46
47
enum vfp_status {
48
        VFP_ERROR = -1,
49
        VFP_OK = 0,
50
        VFP_END = 1,
51
        VFP_NULL = 2,   // signal bypass, never returned by VFP_Suck()
52
};
53
54
typedef enum vfp_status vfp_init_f(VRT_CTX, struct vfp_ctx *,
55
    struct vfp_entry *);
56
typedef enum vfp_status
57
    vfp_pull_f(struct vfp_ctx *, struct vfp_entry *, void *ptr, ssize_t *len);
58
typedef void vfp_fini_f(struct vfp_ctx *, struct vfp_entry *);
59
60
struct vfp {
61
        const char              *name;
62
        vfp_init_f              *init;
63
        vfp_pull_f              *pull;
64
        vfp_fini_f              *fini;
65
        const void              *priv1;
66
};
67
68
struct vfp_entry {
69
        unsigned                magic;
70
#define VFP_ENTRY_MAGIC         0xbe32a027
71
        enum vfp_status         closed;
72
        const struct vfp        *vfp;
73
        void                    *priv1; // XXX ambiguous with priv1 in struct vfp
74
        ssize_t                 priv2;
75
        VTAILQ_ENTRY(vfp_entry) list;
76
        uint64_t                calls;
77
        uint64_t                bytes_out;
78
};
79
80
/*--------------------------------------------------------------------
81
 * VFP filter state
82
 */
83
84
VTAILQ_HEAD(vfp_entry_s, vfp_entry);
85
86
struct vfp_ctx {
87
        unsigned                magic;
88
#define VFP_CTX_MAGIC           0x61d9d3e5
89
        int                     failed;
90
        struct http             *req;
91
        struct http             *resp;
92
        struct worker           *wrk;
93
        struct objcore          *oc; // Only first filter, if at all
94
95
        struct vfp_entry_s      vfp;
96
        struct vfp_entry        *vfp_nxt;
97
        unsigned                obj_flags;
98
};
99
100
enum vfp_status VFP_Suck(struct vfp_ctx *, void *p, ssize_t *lp);
101
enum vfp_status VFP_Error(struct vfp_ctx *, const char *fmt, ...)
102
    v_printflike_(2, 3);
103
104
/* Deliver processors ------------------------------------------------*/
105
106
enum vdp_action {
107
        VDP_NULL,               /* Input buffer valid after call */
108
        VDP_FLUSH,              /* Input buffer will be invalidated */
109
        VDP_END,                /* Last buffer or after, implies VDP_FLUSH */
110
};
111
112
113
typedef int vdp_init_f(VRT_CTX, struct vdp_ctx *, void **priv);
114
/*
115
 * Return value:
116
 *      negative:       Error - abandon delivery
117
 *      zero:           OK
118
 *      positive:       Don't push this VDP anyway
119
 */
120
121
typedef int vdp_fini_f(struct vdp_ctx *, void **priv);
122
typedef int vdp_bytes_f(struct vdp_ctx *, enum vdp_action, void **priv,
123
    const void *ptr, ssize_t len);
124
125
/*
126
 * ============================================================
127
 * vdpio io-vector interface
128
 */
129
typedef int vdpio_init_f(VRT_CTX, struct vdp_ctx *, void **priv, int capacity);
130
/*
131
 * the vdpio_init_f() are called front (object iterator) to back (consumer).
132
 *
133
 * each init function returns the minimum number of io vectors (vscarab
134
 * capacity) that it requires the next filter to accept. This capacity is
135
 * passed to the next init function such that it can allocate sufficient
136
 * space to fulfil the requirement of the previous filter.
137
 *
138
 * Return values:
139
 *   < 0 : Error
140
 *  == 0 ; NOOP, do not push this filter
141
 *  >= 1 : capacity requirement
142
 *
143
 * typedef is shared with upgrade
144
 */
145
146
typedef int vdpio_lease_f(struct vdp_ctx *, struct vdp_entry *, struct vscarab *scarab);
147
/*
148
 * vdpio_lease_f() returns leases provided by this filter layer in the vscarab
149
 * probided by the caller.
150
 *
151
 * called via vdpio_pull(): the last filter is called first by delivery. Each
152
 * filter calls the previous layer for leases. The first filter calls storage.
153
 *
154
 * return values are as for ObjVAIlease()
155
 *
156
 * Other notable differences to vdp_bytes_f:
157
 * - responsible for updating (struct vdp_entry).bytes_in and .calls
158
 *
159
 */
160
161
typedef void vdpio_fini_f(struct vdp_ctx *, void **priv);
162
163
struct vdp {
164
        const char              *name;
165
        vdp_init_f              *init;
166
        vdp_bytes_f             *bytes;
167
        vdp_fini_f              *fini;
168
        const void              *priv1;
169
170
        vdpio_init_f            *io_init;
171
        vdpio_init_f            *io_upgrade;
172
        vdpio_lease_f           *io_lease;
173
        vdpio_fini_f            *io_fini;
174
};
175
176
struct vdp_entry {
177
        unsigned                magic;
178
#define VDP_ENTRY_MAGIC         0x353eb781
179
        enum vdp_action         end;    // VDP_NULL or VDP_END
180
        const struct vdp        *vdp;
181
        void                    *priv;
182
        VTAILQ_ENTRY(vdp_entry) list;
183
        uint64_t                calls;
184
        uint64_t                bytes_in;
185
};
186
187
VTAILQ_HEAD(vdp_entry_s, vdp_entry);
188
189
struct vdp_ctx {
190
        unsigned                magic;
191
#define VDP_CTX_MAGIC           0xee501df7
192
        int                     retval;         // vdpio: error or capacity
193
        uint64_t                bytes_done;     // not used with vdpio
194
        struct vdp_entry_s      vdp;
195
        struct vdp_entry        *nxt;           // not needed for vdpio
196
        struct worker           *wrk;
197
        struct vsl_log          *vsl;
198
        // NULL'ed after the first filter has been pushed
199
        struct objcore          *oc;
200
        // NULL'ed for delivery
201
        struct http             *hp;
202
        intmax_t                *clen;
203
        // only for vdpio
204
        vai_hdl                 vai_hdl;
205
        struct vscaret          *scaret;
206
};
207
208
int VDP_bytes(struct vdp_ctx *, enum vdp_action act, const void *, ssize_t);
209
210
/*
211
 * vdpe == NULL: get lesaes from the last layer
212
 * vdpe != NULL: get leases from the previous layer or storage
213
 *
214
 * conversely to VDP_bytes, vdpio calls happen back (delivery) to front (storage)
215
 *
216
 * ends up in a tail call to the previous layer to save stack space
217
 */
218
static inline int
219 768
vdpio_pull(struct vdp_ctx *vdc, struct vdp_entry *vdpe, struct vscarab *scarab)
220
{
221
222 768
        CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC);
223
224 768
        if (scarab->used == scarab->capacity)
225 0
                return (0);
226
227 768
        if (vdpe == NULL)
228 0
                vdpe = VTAILQ_LAST(&vdc->vdp, vdp_entry_s);
229
        else {
230 768
                CHECK_OBJ(vdpe, VDP_ENTRY_MAGIC);
231 768
                vdpe = VTAILQ_PREV(vdpe, vdp_entry_s, list);
232
        }
233
234 768
        if (vdpe != NULL)
235 768
                return (vdpe->vdp->io_lease(vdc, vdpe, scarab));
236
        else
237 0
                return (ObjVAIlease(vdc->wrk, vdc->vai_hdl, scarab));
238 768
}
239
240
uint64_t VDPIO_Close1(struct vdp_ctx *, struct vdp_entry *vdpe);
241
242
/*
243
 * ============================================================
244
 * VDPIO helpers
245
 */
246
247
/*
248
 * l bytes have been written to buf. save these to out and checkpoint buf for
249
 * the remaining free space
250
 */
251
static inline void
252
iovec_collect(struct iovec *buf, struct iovec *out, size_t l)
253
{
254
        if (l == 0)
255
                return;
256
        if (out->iov_base == NULL)
257
                out->iov_base = buf->iov_base;
258
        assert((char *)out->iov_base + out->iov_len == buf->iov_base);
259
        assert(buf->iov_len >= l);
260
        out->iov_len += l;
261
        buf->iov_base = (char *)buf->iov_base + l;
262
        buf->iov_len -= l;
263
        if (buf->iov_len == 0)
264
                *buf = IOV_NIL;
265
}
266
267
/*
268
 * take at most bytes from the in viov to the out viov
269
 *
270
 * if all remaining have been moved, out inherits the lease
271
 *
272
 * this does not copy, just adjusts the pointers
273
 * out must be zero initialized, unless it acts as a buffer
274
 */
275
static inline size_t
276
viov_take(struct viov *in, struct viov *out, size_t bytes)
277
{
278
        if (bytes > in->iov.iov_len)
279
                bytes = in->iov.iov_len;
280
        iovec_collect(&in->iov, &out->iov, bytes);
281
        if (in->iov.iov_len == 0) {
282
                out->lease = in->lease;
283
                in->lease = VAI_LEASE_NORET;
284
        } else
285
                out->lease = VAI_LEASE_NORET;
286
        return (bytes);
287
}
288
289
/*
290
 * return a single lease via the vdc vscaret
291
 */
292
static inline
293
void vdpio_return_lease(const struct vdp_ctx *vdc, uint64_t lease)
294
{
295
        struct vscaret *scaret;
296
297
        CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC);
298
        scaret = vdc->scaret;
299
        VSCARET_CHECK_NOTNULL(scaret);
300
301
        if (scaret->used == scaret->capacity)
302
                ObjVAIreturn(vdc->wrk, vdc->vai_hdl, scaret);
303
        VSCARET_ADD(scaret, lease);
304
}
305
306
/*
307
 * add all leases from the vscarab to the vscaret
308
 */
309
static inline
310
void vdpio_return_vscarab(const struct vdp_ctx *vdc, struct vscarab *scarab)
311
{
312
        struct viov *v;
313
314
        VSCARAB_CHECK_NOTNULL(scarab);
315
        VSCARAB_FOREACH(v, scarab)
316
                vdpio_return_lease(vdc, v->lease);
317
        AZ(v);
318
        VSCARAB_INIT(scarab, scarab->capacity);
319
}
320
321
/*
322
 * return _leading_ used up iovs (len == 0)
323
 * move remaining to the beginning of the scarab
324
 *
325
 * this does not touch iovs after a non-empty iov, to support
326
 * "return this lease only after iovs before have been processed" semantics
327
 *
328
 * should be called after a scarab has been partly consumed
329
 */
330
331
static inline void
332
vdpio_consolidate_vscarab(const struct vdp_ctx *vdc, struct vscarab *scarab)
333
{
334
        struct viov *v;
335
        unsigned removed;
336
337
        VSCARAB_CHECK_NOTNULL(scarab);
338
339
        if (scarab->used == 0 || scarab->s[0].iov.iov_len > 0)
340
                return;
341
342
        VSCARAB_FOREACH(v, scarab) {
343
                if (v->iov.iov_len > 0)
344
                        break;
345
                AN(v->iov.iov_base);
346
                vdpio_return_lease(vdc, v->lease);
347
        }
348
        if (v == NULL) {
349
                // all returned
350
                scarab->used = 0;
351
                // preserve flags
352
                memset(scarab->s, 0, scarab->capacity * sizeof *v);
353
                return;
354
        }
355
        assert(scarab->s < v);
356
        removed = v - scarab->s;
357
        assert(removed < scarab->used);
358
        scarab->used -= removed;
359
360
        memmove(scarab->s, v, scarab->used * sizeof(*v));
361
        memset(scarab->s + scarab->used, 0, (scarab->capacity - scarab->used) * sizeof *v);
362
}
363
364
// Lifecycle management in cache_deliver_proc.c
365
int VDPIO_Init(struct vdp_ctx *vdc, struct objcore *oc, struct ws *ws,
366
    vai_notify_cb *notify_cb, void *notify_priv, struct vscaret *scaret);
367
void VDPIO_Return(const struct vdp_ctx *vdc);
368
void VDPIO_Notify(struct worker *, const struct vdp_ctx *vdc);
369
void VDPIO_Fini(struct vdp_ctx *vdc);
370
371
/* Registry functions -------------------------------------------------*/
372
const char *VRT_AddFilter(VRT_CTX, const struct vfp *, const struct vdp *);
373
void VRT_RemoveFilter(VRT_CTX, const struct vfp *, const struct vdp *);