varnish-cache/bin/varnishd/cache/cache_deliver_proc.c
1
/*-
2
 * Copyright (c) 2006 Verdens Gang AS
3
 * Copyright (c) 2006-2015 Varnish Software AS
4
 * All rights reserved.
5
 *
6
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
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
#include "config.h"
31
32
#include "cache_varnishd.h"
33
#include "cache_filter.h"
34
35
/* VDP_bytes
36
 *
37
 * Pushes len bytes at ptr down the delivery processor list.
38
 *
39
 * This function picks and calls the next delivery processor from the
40
 * list. The return value is the return value of the delivery
41
 * processor. Upon seeing a non-zero return value, that lowest value
42
 * observed is latched in ->retval and all subsequent calls to
43
 * VDP_bytes will return that value directly without calling the next
44
 * processor.
45
 *
46
 * Valid return values (of VDP_bytes and any VDP function):
47
 * r < 0:  Error, breaks out early on an error condition
48
 * r == 0: Continue
49
 * r > 0:  Stop, breaks out early without error condition
50
 */
51
int
52 3407
VDP_bytes(struct req *req, enum vdp_action act, const void *ptr, ssize_t len)
53
{
54
        int retval;
55
        struct vdp_entry *vdpe;
56
        struct vdp_ctx *vdc;
57
58 3407
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
59 3407
        vdc = req->vdc;
60 3407
        assert(act == VDP_NULL || act == VDP_FLUSH);
61 3407
        if (vdc->retval)
62 3
                return (vdc->retval);
63 3404
        vdpe = vdc->nxt;
64 3404
        CHECK_OBJ_NOTNULL(vdpe, VDP_ENTRY_MAGIC);
65 3404
        vdc->nxt = VTAILQ_NEXT(vdpe, list);
66
67 3404
        assert(act > VDP_NULL || len > 0);
68
        /* Call the present layer, while pointing to the next layer down */
69 3404
        retval = vdpe->vdp->func(req, act, &vdpe->priv, ptr, len);
70 3404
        if (retval && (vdc->retval == 0 || retval < vdc->retval))
71 28
                vdc->retval = retval; /* Latch error value */
72 3404
        vdc->nxt = vdpe;
73 3404
        return (vdc->retval);
74
}
75
76
int
77 1774
VDP_push(struct req *req, const struct vdp *vdp, void *priv, int bottom)
78
{
79
        struct vdp_entry *vdpe;
80
        struct vdp_ctx *vdc;
81
82 1774
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
83 1774
        vdc = req->vdc;
84 1774
        AN(vdp);
85 1774
        AN(vdp->name);
86 1774
        AN(vdp->func);
87
88 1774
        if (vdc->retval)
89 0
                return (vdc->retval);
90
91 1774
        if (DO_DEBUG(DBG_PROCESSORS))
92 0
                VSLb(req->vsl, SLT_Debug, "VDP_push(%s)", vdp->name);
93
94 1774
        vdpe = WS_Alloc(req->ws, sizeof *vdpe);
95 1774
        if (vdpe == NULL) {
96 10
                AZ(vdc->retval);
97 10
                vdc->retval = -1;
98 10
                return (vdc->retval);
99
        }
100 1764
        INIT_OBJ(vdpe, VDP_ENTRY_MAGIC);
101 1764
        vdpe->vdp = vdp;
102 1764
        vdpe->priv = priv;
103 1764
        if (bottom)
104 1661
                VTAILQ_INSERT_TAIL(&vdc->vdp, vdpe, list);
105
        else
106 103
                VTAILQ_INSERT_HEAD(&vdc->vdp, vdpe, list);
107 1764
        vdc->nxt = VTAILQ_FIRST(&vdc->vdp);
108
109 1764
        AZ(vdc->retval);
110 1764
        vdc->retval = vdpe->vdp->func(req, VDP_INIT, &vdpe->priv, NULL, 0);
111 1764
        return (vdc->retval);
112
}
113
114
void
115 2347
VDP_close(struct req *req)
116
{
117
        struct vdp_entry *vdpe;
118
        struct vdp_ctx *vdc;
119
120 2347
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
121 2347
        vdc = req->vdc;
122 6458
        while (!VTAILQ_EMPTY(&vdc->vdp)) {
123 1764
                vdpe = VTAILQ_FIRST(&vdc->vdp);
124 1764
                if (vdc->retval >= 0)
125 1753
                        AN(vdpe);
126 1764
                if (vdpe != NULL) {
127 1764
                        CHECK_OBJ_NOTNULL(vdpe, VDP_ENTRY_MAGIC);
128 1764
                        VTAILQ_REMOVE(&vdc->vdp, vdpe, list);
129 1764
                        AZ(vdpe->vdp->func(req, VDP_FINI, &vdpe->priv,
130
                            NULL, 0));
131 1764
                        AZ(vdpe->priv);
132
                }
133 1764
                vdc->nxt = VTAILQ_FIRST(&vdc->vdp);
134
        }
135 2347
}
136
137
/*--------------------------------------------------------------------*/
138
139
static int v_matchproto_(objiterate_f)
140 1850
vdp_objiterator(void *priv, int flush, const void *ptr, ssize_t len)
141
{
142 1850
        return (VDP_bytes(priv, flush ? VDP_FLUSH : VDP_NULL, ptr, len));
143
}
144
145
146
int
147 1606
VDP_DeliverObj(struct req *req)
148
{
149
        int r;
150
151 1606
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
152 1606
        r = ObjIterate(req->wrk, req->objcore, req, vdp_objiterator,
153 1606
            req->objcore->flags & OC_F_PRIVATE ? 1 : 0);
154 1606
        if (r < 0)
155 18
                return (r);
156 1588
        return (0);
157
}