| | varnish-cache/bin/varnishd/storage/mgt_stevedore.c |
0 |
|
/*- |
1 |
|
* Copyright (c) 2007-2011 Varnish Software AS |
2 |
|
* All rights reserved. |
3 |
|
* |
4 |
|
* Author: Dag-Erling Smørgav <des@des.no> |
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 |
|
* STEVEDORE: one who works at or is responsible for loading and |
30 |
|
* unloading ships in port. Example: "on the wharves, stevedores were |
31 |
|
* unloading cargo from the far corners of the world." Origin: Spanish |
32 |
|
* estibador, from estibar to pack. First Known Use: 1788 |
33 |
|
*/ |
34 |
|
|
35 |
|
#include "config.h" |
36 |
|
|
37 |
|
#include <stdio.h> |
38 |
|
#include <stdlib.h> |
39 |
|
#include <string.h> |
40 |
|
#include <unistd.h> |
41 |
|
|
42 |
|
#include "mgt/mgt.h" |
43 |
|
#include "common/heritage.h" |
44 |
|
#include "vcli_serve.h" |
45 |
|
|
46 |
|
#include "storage/storage.h" |
47 |
|
|
48 |
|
VTAILQ_HEAD(stevedore_head, stevedore); |
49 |
|
|
50 |
|
static struct stevedore_head proto_stevedores = |
51 |
|
VTAILQ_HEAD_INITIALIZER(proto_stevedores); |
52 |
|
|
53 |
|
static struct stevedore_head pre_stevedores = |
54 |
|
VTAILQ_HEAD_INITIALIZER(pre_stevedores); |
55 |
|
|
56 |
|
static struct stevedore_head stevedores = |
57 |
|
VTAILQ_HEAD_INITIALIZER(stevedores); |
58 |
|
|
59 |
|
/* Name of transient storage */ |
60 |
|
#define TRANSIENT_STORAGE "Transient" |
61 |
|
|
62 |
|
struct stevedore *stv_transient; |
63 |
|
|
64 |
|
const char *mgt_stv_h2_rxbuf; |
65 |
|
|
66 |
|
/*--------------------------------------------------------------------*/ |
67 |
|
|
68 |
|
int |
69 |
1028021 |
STV__iter(struct stevedore ** const pp) |
70 |
|
{ |
71 |
|
|
72 |
1028021 |
AN(pp); |
73 |
1028021 |
CHECK_OBJ_ORNULL(*pp, STEVEDORE_MAGIC); |
74 |
1028021 |
if (*pp != NULL) |
75 |
644600 |
*pp = VTAILQ_NEXT(*pp, list); |
76 |
383421 |
else if (!VTAILQ_EMPTY(&stevedores)) |
77 |
285261 |
*pp = VTAILQ_FIRST(&stevedores); |
78 |
|
else |
79 |
98160 |
*pp = VTAILQ_FIRST(&pre_stevedores); |
80 |
1028021 |
return (*pp != NULL); |
81 |
|
} |
82 |
|
|
83 |
|
/*--------------------------------------------------------------------*/ |
84 |
|
|
85 |
|
static void v_matchproto_(cli_func_t) |
86 |
160 |
stv_cli_list(struct cli *cli, const char * const *av, void *priv) |
87 |
|
{ |
88 |
|
struct stevedore *stv; |
89 |
|
|
90 |
160 |
ASSERT_MGT(); |
91 |
160 |
(void)av; |
92 |
160 |
(void)priv; |
93 |
160 |
VCLI_Out(cli, "Storage devices:\n"); |
94 |
520 |
STV_Foreach(stv) |
95 |
360 |
VCLI_Out(cli, "\tstorage.%s = %s\n", stv->ident, stv->name); |
96 |
160 |
} |
97 |
|
|
98 |
|
static void v_matchproto_(cli_func_t) |
99 |
40 |
stv_cli_list_json(struct cli *cli, const char * const *av, void *priv) |
100 |
|
{ |
101 |
|
struct stevedore *stv; |
102 |
40 |
int n = 0; |
103 |
|
|
104 |
40 |
(void)priv; |
105 |
40 |
ASSERT_MGT(); |
106 |
40 |
VCLI_JSON_begin(cli, 2, av); |
107 |
40 |
VCLI_Out(cli, ",\n"); |
108 |
120 |
STV_Foreach(stv) { |
109 |
80 |
VCLI_Out(cli, "%s", n ? ",\n" : ""); |
110 |
80 |
n++; |
111 |
80 |
VCLI_Out(cli, "{\n"); |
112 |
80 |
VSB_indent(cli->sb, 2); |
113 |
80 |
VCLI_Out(cli, "\"name\": "); |
114 |
80 |
VCLI_JSON_str(cli, stv->ident); |
115 |
80 |
VCLI_Out(cli, ",\n"); |
116 |
80 |
VCLI_Out(cli, "\"storage\": "); |
117 |
80 |
VCLI_JSON_str(cli, stv->name); |
118 |
80 |
VSB_indent(cli->sb, -2); |
119 |
80 |
VCLI_Out(cli, "\n}"); |
120 |
|
} |
121 |
40 |
VCLI_JSON_end(cli); |
122 |
40 |
} |
123 |
|
|
124 |
|
/*--------------------------------------------------------------------*/ |
125 |
|
|
126 |
|
static struct cli_proto cli_stv[] = { |
127 |
|
{ CLICMD_STORAGE_LIST, "", stv_cli_list, stv_cli_list_json }, |
128 |
|
{ NULL} |
129 |
|
}; |
130 |
|
|
131 |
|
/*-------------------------------------------------------------------- |
132 |
|
*/ |
133 |
|
|
134 |
|
#ifdef WITH_PERSISTENT_STORAGE |
135 |
|
static void v_noreturn_ v_matchproto_(storage_init_f) |
136 |
40 |
smp_fake_init(struct stevedore *parent, int ac, char * const *av) |
137 |
|
{ |
138 |
|
|
139 |
40 |
(void)parent; |
140 |
40 |
(void)ac; |
141 |
40 |
(void)av; |
142 |
40 |
ARGV_ERR( |
143 |
|
"-spersistent has been deprecated, please see:\n" |
144 |
|
" https://www.varnish-cache.org/docs/trunk/phk/persistent.html\n" |
145 |
|
"for details.\n" |
146 |
|
); |
147 |
0 |
} |
148 |
|
|
149 |
|
static const struct stevedore smp_fake_stevedore = { |
150 |
|
.magic = STEVEDORE_MAGIC, |
151 |
|
.name = "persistent", |
152 |
|
.init = smp_fake_init, |
153 |
|
}; |
154 |
|
#endif |
155 |
|
|
156 |
|
/*-------------------------------------------------------------------- |
157 |
|
* Register a stevedore implementation by name. |
158 |
|
* VEXTs get to do this first, and since the list is searched front to |
159 |
|
* back a VEXT stevedore which inadvisably wants to steal "default" or |
160 |
|
* the name of another stevedore implementation can do so. |
161 |
|
*/ |
162 |
|
|
163 |
|
void |
164 |
220740 |
STV_Register(const struct stevedore *cstv, const char *altname) |
165 |
|
{ |
166 |
|
struct stevedore *stv; |
167 |
|
|
168 |
220740 |
CHECK_OBJ_NOTNULL(cstv, STEVEDORE_MAGIC); |
169 |
220740 |
ALLOC_OBJ(stv, STEVEDORE_MAGIC); |
170 |
220740 |
AN(stv); |
171 |
220740 |
*stv = *cstv; |
172 |
220740 |
if (altname != NULL) |
173 |
36790 |
stv->ident = altname; |
174 |
|
else |
175 |
183950 |
stv->ident = stv->name; |
176 |
220740 |
VTAILQ_INSERT_TAIL(&proto_stevedores, stv, list); |
177 |
220740 |
} |
178 |
|
|
179 |
|
static void |
180 |
36790 |
STV_Register_The_Usual_Suspects(void) |
181 |
|
{ |
182 |
36790 |
STV_Register(&smf_stevedore, NULL); |
183 |
36790 |
STV_Register(&sma_stevedore, NULL); |
184 |
36790 |
STV_Register(&smd_stevedore, NULL); |
185 |
|
#ifdef WITH_PERSISTENT_STORAGE |
186 |
36790 |
STV_Register(&smp_stevedore, NULL); |
187 |
36790 |
STV_Register(&smp_fake_stevedore, NULL); |
188 |
|
#endif |
189 |
|
#if defined(HAVE_UMEM_H) |
190 |
|
STV_Register(&smu_stevedore, NULL); |
191 |
|
STV_Register(&smu_stevedore, "default"); |
192 |
|
#else |
193 |
36790 |
STV_Register(&sma_stevedore, "default"); |
194 |
|
#endif |
195 |
36790 |
} |
196 |
|
|
197 |
|
/*-------------------------------------------------------------------- |
198 |
|
* Parse a stevedore argument on the form: |
199 |
|
* [ name '=' ] strategy [ ',' arg ] * |
200 |
|
*/ |
201 |
|
|
202 |
|
void |
203 |
76440 |
STV_Config(const char *spec) |
204 |
|
{ |
205 |
|
char **av, buf[8]; |
206 |
|
const char *ident; |
207 |
|
struct stevedore *stv; |
208 |
|
static unsigned seq = 0; |
209 |
|
|
210 |
76440 |
av = MGT_NamedArg(spec, &ident, "-s"); |
211 |
76440 |
AN(av); |
212 |
|
|
213 |
76440 |
if (av[1] == NULL) |
214 |
0 |
ARGV_ERR("-s argument lacks strategy {malloc, file, ...}\n"); |
215 |
|
|
216 |
|
/* Append strategy to ident string */ |
217 |
76440 |
VSB_printf(vident, ",-s%s", av[1]); |
218 |
|
|
219 |
76440 |
if (ident == NULL) { |
220 |
37200 |
bprintf(buf, "s%u", seq++); |
221 |
37200 |
ident = strdup(buf); |
222 |
37200 |
} |
223 |
|
|
224 |
115440 |
VTAILQ_FOREACH(stv, &pre_stevedores, list) |
225 |
39120 |
if (!strcmp(stv->ident, ident)) |
226 |
120 |
ARGV_ERR("(-s %s) '%s' is already defined\n", |
227 |
|
spec, ident); |
228 |
|
|
229 |
76320 |
ALLOC_OBJ(stv, STEVEDORE_MAGIC); |
230 |
76320 |
AN(stv); |
231 |
76320 |
stv->av = av; |
232 |
76320 |
stv->ident = ident; |
233 |
76320 |
stv->name = av[1]; |
234 |
76320 |
VTAILQ_INSERT_TAIL(&pre_stevedores, stv, list); |
235 |
76320 |
} |
236 |
|
|
237 |
|
/*--------------------------------------------------------------------*/ |
238 |
|
|
239 |
|
void |
240 |
38040 |
STV_Config_Final(void) |
241 |
|
{ |
242 |
|
struct stevedore *stv; |
243 |
38040 |
ASSERT_MGT(); |
244 |
|
|
245 |
38040 |
VCLS_AddFunc(mgt_cls, MCF_AUTH, cli_stv); |
246 |
76120 |
STV_Foreach(stv) |
247 |
38880 |
if (!strcmp(stv->ident, TRANSIENT_STORAGE)) |
248 |
800 |
return; |
249 |
37240 |
STV_Config(TRANSIENT_STORAGE "=default"); |
250 |
38040 |
} |
251 |
|
|
252 |
|
/*-------------------------------------------------------------------- |
253 |
|
* Initialize configured stevedores in the worker process |
254 |
|
*/ |
255 |
|
|
256 |
|
void |
257 |
36950 |
STV_Init(void) |
258 |
|
{ |
259 |
|
char **av; |
260 |
|
const char *ident; |
261 |
|
struct stevedore *stv; |
262 |
|
const struct stevedore *stv2; |
263 |
|
int ac; |
264 |
|
|
265 |
36950 |
STV_Register_The_Usual_Suspects(); |
266 |
110610 |
while (!VTAILQ_EMPTY(&pre_stevedores)) { |
267 |
73980 |
stv = VTAILQ_FIRST(&pre_stevedores); |
268 |
73980 |
VTAILQ_REMOVE(&pre_stevedores, stv, list); |
269 |
73980 |
CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC); |
270 |
73980 |
AN(stv->av); |
271 |
73980 |
av = stv->av; |
272 |
73980 |
AN(stv->ident); |
273 |
73980 |
ident = stv->ident; |
274 |
|
|
275 |
113290 |
for (ac = 0; av[ac + 2] != NULL; ac++) |
276 |
39310 |
continue; |
277 |
|
|
278 |
436870 |
VTAILQ_FOREACH(stv2, &proto_stevedores, list) |
279 |
436710 |
if (!strcmp(stv2->ident, av[1])) |
280 |
73820 |
break; |
281 |
73980 |
if (stv2 == NULL) |
282 |
0 |
ARGV_ERR("Unknown stevedore method \"%s\"\n", av[1]); |
283 |
|
|
284 |
73660 |
CHECK_OBJ_NOTNULL(stv2, STEVEDORE_MAGIC); |
285 |
73660 |
*stv = *stv2; |
286 |
73660 |
AN(stv->name); |
287 |
|
|
288 |
73660 |
av += 2; |
289 |
|
|
290 |
73660 |
stv->ident = ident; |
291 |
73660 |
stv->av = av; |
292 |
|
|
293 |
73660 |
if (stv->init != NULL) |
294 |
73660 |
stv->init(stv, ac, av); |
295 |
0 |
else if (ac != 0) |
296 |
0 |
ARGV_ERR("(-s %s) too many arguments\n", stv->name); |
297 |
|
|
298 |
73660 |
AN(stv->allocobj); |
299 |
73660 |
AN(stv->methods); |
300 |
|
|
301 |
73660 |
if (!strcmp(stv->ident, TRANSIENT_STORAGE)) { |
302 |
36630 |
AZ(stv_transient); |
303 |
36630 |
stv_transient = stv; |
304 |
36630 |
} else |
305 |
37030 |
VTAILQ_INSERT_TAIL(&stevedores, stv, list); |
306 |
|
/* NB: Do not free av, stevedore gets to keep it */ |
307 |
|
} |
308 |
36630 |
AN(stv_transient); |
309 |
36630 |
VTAILQ_INSERT_TAIL(&stevedores, stv_transient, list); |
310 |
36630 |
} |