varnish-cache/bin/varnishd/cache/cache_req.c
1
/*-
2
 * Copyright (c) 2006 Verdens Gang AS
3
 * Copyright (c) 2006-2011 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
 * Request management
30
 *
31
 */
32
33
#include "config.h"
34
35
#include "cache_varnishd.h"
36
#include "cache_filter.h"
37
38
#include <stdio.h>
39
#include <stdlib.h>
40
41
#include "cache_pool.h"
42
#include "cache_transport.h"
43
44
#include "vtim.h"
45
46
void
47 43703
Req_AcctLogCharge(struct VSC_main *ds, struct req *req)
48
{
49
        struct acct_req *a;
50
51 43703
        AN(ds);
52 43703
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
53
54 43703
        a = &req->acct;
55
56 43703
        if (req->vsl->wid && !(req->res_mode & RES_PIPE)) {
57 30108
                VSLb(req->vsl, SLT_ReqAcct, "%ju %ju %ju %ju %ju %ju",
58 30108
                    (uintmax_t)a->req_hdrbytes,
59 30108
                    (uintmax_t)a->req_bodybytes,
60 30108
                    (uintmax_t)(a->req_hdrbytes + a->req_bodybytes),
61 30108
                    (uintmax_t)a->resp_hdrbytes,
62 30108
                    (uintmax_t)a->resp_bodybytes,
63 30108
                    (uintmax_t)(a->resp_hdrbytes + a->resp_bodybytes));
64
        }
65
66
        /* Charge to main byte counters (except for ESI subrequests) */
67
#define ACCT(foo)                       \
68
        if (req->esi_level == 0)        \
69
                ds->s_##foo += a->foo;  \
70
        a->foo = 0;
71
#include "tbl/acct_fields_req.h"
72 43704
}
73
74
/*--------------------------------------------------------------------
75
 * Alloc/Free a request
76
 */
77
78
struct req *
79 23700
Req_New(const struct worker *wrk, struct sess *sp)
80
{
81
        struct pool *pp;
82
        struct req *req;
83
        uint16_t nhttp;
84
        unsigned sz, hl;
85
        char *p, *e;
86
87 23700
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
88 23700
        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
89 23700
        pp = sp->pool;
90 23700
        CHECK_OBJ_NOTNULL(pp, POOL_MAGIC);
91
92 23700
        req = MPL_Get(pp->mpl_req, &sz);
93 23700
        AN(req);
94 23700
        req->magic = REQ_MAGIC;
95 23700
        req->sp = sp;
96 23700
        req->top = req; // esi overrides
97
98 23700
        e = (char*)req + sz;
99 23700
        p = (char*)(req + 1);
100 23700
        p = (void*)PRNDUP(p);
101 23700
        assert(p < e);
102
103 23700
        nhttp = (uint16_t)cache_param->http_max_hdr;
104 23700
        hl = HTTP_estimate(nhttp);
105
106 23700
        req->http = HTTP_create(p, nhttp, hl);
107 23700
        p += hl;
108 23700
        p = (void*)PRNDUP(p);
109 23700
        assert(p < e);
110
111 23700
        req->http0 = HTTP_create(p, nhttp, hl);
112 23700
        p += hl;
113 23700
        p = (void*)PRNDUP(p);
114 23700
        assert(p < e);
115
116 23700
        req->resp = HTTP_create(p, nhttp, hl);
117 23700
        p += hl;
118 23700
        p = (void*)PRNDUP(p);
119 23700
        assert(p < e);
120
121 23700
        sz = cache_param->vsl_buffer;
122 23700
        VSL_Setup(req->vsl, p, sz);
123 23700
        p += sz;
124 23700
        p = (void*)PRNDUP(p);
125
126 23700
        req->vfc = (void*)p;
127 23700
        INIT_OBJ(req->vfc, VFP_CTX_MAGIC);
128 23700
        p = (void*)PRNDUP(p + sizeof(*req->vfc));
129
130 23700
        req->htc = (void*)p;
131 23700
        p = (void*)PRNDUP(p + sizeof(*req->htc));
132
133 23700
        req->vdc = (void*)p;
134 23700
        INIT_OBJ(req->vdc, VDP_CTX_MAGIC);
135 23700
        VTAILQ_INIT(&req->vdc->vdp);
136 23700
        p = (void*)PRNDUP(p + sizeof(*req->vdc));
137
138 23700
        req->htc = (void*)p;
139 23700
        INIT_OBJ(req->htc, HTTP_CONN_MAGIC);
140 23700
        p = (void*)PRNDUP(p + sizeof(*req->htc));
141
142 23700
        assert(p < e);
143
144 23700
        WS_Init(req->ws, "req", p, e - p);
145
146 23700
        req->req_bodybytes = 0;
147
148 23700
        req->t_first = NAN;
149 23700
        req->t_prev = NAN;
150 23700
        req->t_req = NAN;
151
152 23700
        VRTPRIV_init(req->privs);
153
154 23700
        return (req);
155
}
156
157
void
158 23616
Req_Release(struct req *req)
159
{
160
        struct sess *sp;
161
        struct pool *pp;
162
163 23616
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
164
165
        /* Make sure the request counters have all been zeroed */
166
#define ACCT(foo) \
167
        AZ(req->acct.foo);
168
#include "tbl/acct_fields_req.h"
169
170 23616
        AZ(req->vcl);
171 23616
        if (req->vsl->wid)
172 2976
                VSL_End(req->vsl);
173 23615
        sp = req->sp;
174 23615
        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
175 23615
        pp = sp->pool;
176 23615
        CHECK_OBJ_NOTNULL(pp, POOL_MAGIC);
177 23615
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
178 23615
        MPL_AssertSane(req);
179 23615
        VSL_Flush(req->vsl, 0);
180 23616
        req->sp = NULL;
181 23616
        MPL_Free(pp->mpl_req, req);
182 23616
}
183
184
static void
185 29556
req_finalize(struct req *req)
186
{
187 29556
        VRTPRIV_dynamic_kill(req->privs, (uintptr_t)req);
188 29555
        VRTPRIV_dynamic_kill(req->privs, (uintptr_t)&req->top);
189 29555
        assert(VTAILQ_EMPTY(&req->privs->privs));
190 29555
}
191
192
/*----------------------------------------------------------------------
193
 * TODO:
194
 * - check for code duplication with cnt_recv_prep
195
 * - re-check if complete
196
 */
197
198
void
199 1248
Req_Rollback(struct req *req)
200
{
201 1248
        req_finalize(req);
202 1248
        HTTP_Copy(req->http, req->http0);
203 1248
        WS_Reset(req->ws, req->ws_req);
204 1248
}
205
206
/*----------------------------------------------------------------------
207
 * TODO: remove code duplication with cnt_recv_prep
208
 */
209
210
void
211 28308
Req_Cleanup(struct sess *sp, struct worker *wrk, struct req *req)
212
{
213
214 28308
        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
215 28308
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
216 28308
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
217 28308
        assert(sp == req->sp);
218
219 28308
        req->director_hint = NULL;
220 28308
        req->restarts = 0;
221
222 28308
        AZ(req->esi_level);
223 28308
        assert(req->top == req);
224
225 28308
        if (req->vcl != NULL) {
226 26448
                if (wrk->vcl != NULL)
227 109
                        VCL_Rel(&wrk->vcl);
228 26448
                wrk->vcl = req->vcl;
229 26448
                req->vcl = NULL;
230
        }
231
232 28308
        req_finalize(req);
233
234
        /* Charge and log byte counters */
235 28307
        if (req->vsl->wid) {
236 27275
                Req_AcctLogCharge(wrk->stats, req);
237 27276
                VSL_End(req->vsl);
238
        }
239 28308
        req->req_bodybytes = 0;
240
241 28308
        if (!isnan(req->t_prev) && req->t_prev > 0. && req->t_prev > sp->t_idle)
242 26301
                sp->t_idle = req->t_prev;
243
        else
244 2007
                sp->t_idle = W_TIM_real(wrk);
245
246 28308
        req->t_first = NAN;
247 28308
        req->t_prev = NAN;
248 28308
        req->t_req = NAN;
249 28308
        req->req_body_status = REQ_BODY_INIT;
250
251 28308
        req->hash_always_miss = 0;
252 28308
        req->hash_ignore_busy = 0;
253 28308
        req->is_hit = 0;
254
255 28308
        WS_Reset(req->ws, 0);
256 28308
}
257
258
/*----------------------------------------------------------------------
259
 */
260
261
void v_matchproto_(vtr_req_fail_f)
262 168
Req_Fail(struct req *req, enum sess_close reason)
263
{
264 168
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
265
266 168
        AN(req->transport->req_fail);
267 168
        req->transport->req_fail(req, reason);
268 168
}