|  |  | varnish-cache/bin/varnishd/cache/cache_busyobj.c | 
|---|
| 0 |  | /*- | 
| 1 |  |  * Copyright (c) 2013-2015 Varnish Software AS | 
| 2 |  |  * All rights reserved. | 
| 3 |  |  * | 
| 4 |  |  * Author: Martin Blix Grydeland <martin@varnish-software.com> | 
| 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 |  |  * Handle backend connections and backend request structures. | 
| 31 |  |  * | 
| 32 |  |  */ | 
| 33 |  |  | 
| 34 |  | #include "config.h" | 
| 35 |  |  | 
| 36 |  | #include <stdlib.h> | 
| 37 |  |  | 
| 38 |  | #include "cache_varnishd.h" | 
| 39 |  | #include "cache_filter.h" | 
| 40 |  | #include "cache_objhead.h" | 
| 41 |  |  | 
| 42 |  | static struct mempool           *vbopool; | 
| 43 |  |  | 
| 44 |  | /*-------------------------------------------------------------------- | 
| 45 |  |  */ | 
| 46 |  |  | 
| 47 |  | void | 
| 48 | 12363 | VBO_Init(void) | 
| 49 |  | { | 
| 50 |  |  | 
| 51 | 24726 |         vbopool = MPL_New("busyobj", &cache_param->pool_vbo, | 
| 52 | 12363 |             &cache_param->workspace_backend); | 
| 53 | 12363 |         AN(vbopool); | 
| 54 | 12363 | } | 
| 55 |  |  | 
| 56 |  | /*-------------------------------------------------------------------- | 
| 57 |  |  * BusyObj handling | 
| 58 |  |  */ | 
| 59 |  |  | 
| 60 |  | struct busyobj * | 
| 61 | 30043 | VBO_GetBusyObj(const struct worker *wrk, const struct req *req) | 
| 62 |  | { | 
| 63 |  |         struct busyobj *bo; | 
| 64 |  |         uint16_t nhttp; | 
| 65 |  |         unsigned sz; | 
| 66 |  |         char *p; | 
| 67 |  |  | 
| 68 | 30043 |         CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); | 
| 69 |  |  | 
| 70 | 30043 |         bo = MPL_Get(vbopool, &sz); | 
| 71 | 30043 |         XXXAN(bo); | 
| 72 | 30043 |         bo->magic = BUSYOBJ_MAGIC; | 
| 73 | 30043 |         bo->end = (char *)bo + sz; | 
| 74 | 30043 |         bo->max_retries = cache_param->max_retries; | 
| 75 |  |  | 
| 76 | 30043 |         p = (void*)(bo + 1); | 
| 77 | 30043 |         p = (void*)PRNDUP(p); | 
| 78 | 30043 |         assert(p < bo->end); | 
| 79 |  |  | 
| 80 | 30043 |         nhttp = (uint16_t)cache_param->http_max_hdr; | 
| 81 | 30043 |         sz = HTTP_estimate(nhttp); | 
| 82 |  |  | 
| 83 | 30043 |         bo->bereq0 = HTTP_create(p, nhttp, sz); | 
| 84 | 30043 |         p += sz; | 
| 85 | 30043 |         p = (void*)PRNDUP(p); | 
| 86 | 30043 |         assert(p < bo->end); | 
| 87 |  |  | 
| 88 | 30043 |         bo->bereq = HTTP_create(p, nhttp, sz); | 
| 89 | 30043 |         p += sz; | 
| 90 | 30043 |         p = (void*)PRNDUP(p); | 
| 91 | 30043 |         assert(p < bo->end); | 
| 92 |  |  | 
| 93 | 30043 |         bo->beresp = HTTP_create(p, nhttp, sz); | 
| 94 | 30043 |         p += sz; | 
| 95 | 30043 |         p = (void*)PRNDUP(p); | 
| 96 | 30043 |         assert(p < bo->end); | 
| 97 |  |  | 
| 98 | 30043 |         sz = cache_param->vsl_buffer; | 
| 99 | 30043 |         VSL_Setup(bo->vsl, p, sz); | 
| 100 | 30043 |         bo->vsl->wid = VXID_Get(wrk, VSL_BACKENDMARKER); | 
| 101 | 30043 |         p += sz; | 
| 102 | 30043 |         p = (void*)PRNDUP(p); | 
| 103 | 30043 |         assert(p < bo->end); | 
| 104 |  |  | 
| 105 | 30043 |         bo->vfc = (void*)p; | 
| 106 | 30043 |         p += sizeof (*bo->vfc); | 
| 107 | 30043 |         p = (void*)PRNDUP(p); | 
| 108 | 30043 |         INIT_OBJ(bo->vfc, VFP_CTX_MAGIC); | 
| 109 |  |  | 
| 110 | 30043 |         WS_Init(bo->ws, "bo", p, bo->end - p); | 
| 111 |  |  | 
| 112 | 30043 |         bo->do_stream = 1; | 
| 113 |  |  | 
| 114 | 30043 |         if (req->client_identity != NULL) { | 
| 115 | 13 |                 bo->client_identity = WS_Copy(bo->ws, req->client_identity, -1); | 
| 116 | 13 |                 XXXAN(bo->client_identity); | 
| 117 | 13 |         } | 
| 118 |  |  | 
| 119 | 30043 |         VRT_Assign_Backend(&bo->director_req, req->director_hint); | 
| 120 | 30043 |         bo->vcl = req->vcl; | 
| 121 | 30043 |         VCL_Ref(bo->vcl); | 
| 122 |  |  | 
| 123 | 30043 |         bo->t_first = bo->t_prev = NAN; | 
| 124 | 30043 |         bo->connect_timeout = NAN; | 
| 125 | 30043 |         bo->first_byte_timeout = NAN; | 
| 126 | 30043 |         bo->between_bytes_timeout = NAN; | 
| 127 |  |  | 
| 128 | 30043 |         memcpy(bo->digest, req->digest, sizeof bo->digest); | 
| 129 |  |  | 
| 130 | 30043 |         return (bo); | 
| 131 |  | } | 
| 132 |  |  | 
| 133 |  | void | 
| 134 | 30029 | VBO_ReleaseBusyObj(struct worker *wrk, struct busyobj **pbo) | 
| 135 |  | { | 
| 136 |  |         struct busyobj *bo; | 
| 137 |  |  | 
| 138 | 30029 |         CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); | 
| 139 | 30029 |         TAKE_OBJ_NOTNULL(bo, pbo, BUSYOBJ_MAGIC); | 
| 140 | 30029 |         CHECK_OBJ_ORNULL(bo->fetch_objcore, OBJCORE_MAGIC); | 
| 141 |  |  | 
| 142 | 30029 |         AZ(bo->htc); | 
| 143 | 30029 |         AZ(bo->stale_oc); | 
| 144 |  |  | 
| 145 | 60058 |         VSLb(bo->vsl, SLT_BereqAcct, "%ju %ju %ju %ju %ju %ju", | 
| 146 | 30029 |             (uintmax_t)bo->acct.bereq_hdrbytes, | 
| 147 | 30029 |             (uintmax_t)bo->acct.bereq_bodybytes, | 
| 148 | 30029 |             (uintmax_t)(bo->acct.bereq_hdrbytes + bo->acct.bereq_bodybytes), | 
| 149 | 30029 |             (uintmax_t)bo->acct.beresp_hdrbytes, | 
| 150 | 30029 |             (uintmax_t)bo->acct.beresp_bodybytes, | 
| 151 | 30029 |             (uintmax_t)(bo->acct.beresp_hdrbytes + bo->acct.beresp_bodybytes)); | 
| 152 |  |  | 
| 153 | 30029 |         VSL_End(bo->vsl); | 
| 154 |  |  | 
| 155 | 30029 |         if (WS_Overflowed(bo->ws)) | 
| 156 | 2210 |                 wrk->stats->ws_backend_overflow++; | 
| 157 |  |  | 
| 158 | 30029 |         if (bo->fetch_objcore != NULL) { | 
| 159 | 29640 |                 (void)HSH_DerefObjCore(wrk, &bo->fetch_objcore); | 
| 160 | 29640 |         } | 
| 161 |  |  | 
| 162 | 30029 |         VRT_Assign_Backend(&bo->director_req, NULL); | 
| 163 | 30029 |         VRT_Assign_Backend(&bo->director_resp, NULL); | 
| 164 | 30029 |         VCL_Rel(&bo->vcl); | 
| 165 |  | #ifdef ENABLE_WORKSPACE_EMULATOR | 
| 166 |  |         WS_Rollback(bo->ws, 0); | 
| 167 |  | #endif | 
| 168 |  |  | 
| 169 | 30029 |         MPL_Free(vbopool, bo); | 
| 170 | 30029 | } | 
| 171 |  |  | 
| 172 |  | void | 
| 173 | 70120 | VBO_SetState(struct worker *wrk, struct busyobj *bo, enum boc_state_e next) | 
| 174 |  | { | 
| 175 |  |         unsigned broadcast; | 
| 176 |  |  | 
| 177 | 70120 |         CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); | 
| 178 | 70120 |         CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); | 
| 179 |  |  | 
| 180 | 70120 |         switch (next) { | 
| 181 |  |         case BOS_REQ_DONE: | 
| 182 | 29378 |                 AN(bo->req); | 
| 183 | 29378 |                 bo->req = NULL; | 
| 184 | 29378 |                 broadcast = bo->is_bgfetch; | 
| 185 | 29378 |                 break; | 
| 186 |  |         case BOS_STREAM: | 
| 187 | 11102 |                 AN(bo->do_stream); | 
| 188 | 11102 |                 AZ(bo->req); | 
| 189 | 11102 |                 broadcast = 1; | 
| 190 | 11102 |                 break; | 
| 191 |  |         case BOS_FINISHED: | 
| 192 |  |         case BOS_FAILED: | 
| 193 |  |                 /* We can't assert that either state already released its | 
| 194 |  |                  * request because a fetch may fail before reaching the | 
| 195 |  |                  * BOS_REQ_DONE state. Failing can also mean executing | 
| 196 |  |                  * vcl_backend_error and reaching BOS_FINISHED from there. | 
| 197 |  |                  * One can legitemately return(retry) from there and proceed | 
| 198 |  |                  * again with a usable req if a return(error) transition led | 
| 199 |  |                  * to vcl_backend_error instead of a failed fetch attempt. | 
| 200 |  |                  */ | 
| 201 | 29640 |                 bo->req = NULL; | 
| 202 | 29640 |                 broadcast = 1; | 
| 203 | 29640 |                 break; | 
| 204 |  |         default: | 
| 205 | 0 |                 WRONG("unexpected BOC state"); | 
| 206 | 0 |         } | 
| 207 |  |  | 
| 208 | 70120 |         ObjSetState(wrk, bo->fetch_objcore, next, broadcast); | 
| 209 | 70120 | } |