| | varnish-cache/lib/libvarnishapi/vsc.c |
0 |
|
/*- |
1 |
|
* Copyright (c) 2006 Verdens Gang AS |
2 |
|
* Copyright (c) 2006-2015 Varnish Software AS |
3 |
|
* All rights reserved. |
4 |
|
* |
5 |
|
* Author: Poul-Henning Kamp <phk@phk.freebsd.dk> |
6 |
|
* Author: Martin Blix Grydeland <martin@varnish-software.com> |
7 |
|
* |
8 |
|
* SPDX-License-Identifier: BSD-2-Clause |
9 |
|
* |
10 |
|
* Redistribution and use in source and binary forms, with or without |
11 |
|
* modification, are permitted provided that the following conditions |
12 |
|
* are met: |
13 |
|
* 1. Redistributions of source code must retain the above copyright |
14 |
|
* notice, this list of conditions and the following disclaimer. |
15 |
|
* 2. Redistributions in binary form must reproduce the above copyright |
16 |
|
* notice, this list of conditions and the following disclaimer in the |
17 |
|
* documentation and/or other materials provided with the distribution. |
18 |
|
* |
19 |
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
20 |
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
21 |
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
22 |
|
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE |
23 |
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
24 |
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
25 |
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
26 |
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
27 |
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
28 |
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
29 |
|
* SUCH DAMAGE. |
30 |
|
*/ |
31 |
|
|
32 |
|
#include "config.h" |
33 |
|
|
34 |
|
#include <sys/stat.h> |
35 |
|
|
36 |
|
#include <fnmatch.h> |
37 |
|
#include <stdint.h> |
38 |
|
#include <stdio.h> |
39 |
|
#include <stdlib.h> |
40 |
|
#include <string.h> |
41 |
|
#include <unistd.h> |
42 |
|
|
43 |
|
#include "vdef.h" |
44 |
|
#include "vas.h" |
45 |
|
#include "miniobj.h" |
46 |
|
#include "vqueue.h" |
47 |
|
#include "vjsn.h" |
48 |
|
#include "vsb.h" |
49 |
|
#include "vsc_priv.h" |
50 |
|
#include "vmb.h" |
51 |
|
|
52 |
|
#include "vapi/vsc.h" |
53 |
|
#include "vapi/vsm.h" |
54 |
|
|
55 |
|
struct vsc_sf_mode { |
56 |
|
const char *name; |
57 |
|
unsigned include; |
58 |
|
unsigned fail; |
59 |
|
unsigned append; |
60 |
|
}; |
61 |
|
|
62 |
|
static const struct vsc_sf_mode VSC_SF_INCLUDE[1] = {{"include", 1, 1, 1}}; |
63 |
|
static const struct vsc_sf_mode VSC_SF_EXCLUDE[1] = {{"exclude", 0, 0, 1}}; |
64 |
|
static const struct vsc_sf_mode VSC_SF_REQUIRE[1] = {{"require", 1, 0, 0}}; |
65 |
|
|
66 |
|
struct vsc_sf { |
67 |
|
unsigned magic; |
68 |
|
#define VSC_SF_MAGIC 0x558478dd |
69 |
|
VTAILQ_ENTRY(vsc_sf) list; |
70 |
|
char *pattern; |
71 |
|
const struct vsc_sf_mode *mode; |
72 |
|
}; |
73 |
|
|
74 |
|
VTAILQ_HEAD(vsc_sf_head, vsc_sf); |
75 |
|
|
76 |
|
struct vsc_pt { |
77 |
|
struct VSC_point point; |
78 |
|
char *name; |
79 |
|
}; |
80 |
|
|
81 |
|
struct vsc_seg { |
82 |
|
unsigned magic; |
83 |
|
#define VSC_SEG_MAGIC 0x801177d4 |
84 |
|
VTAILQ_ENTRY(vsc_seg) list; |
85 |
|
struct vsm_fantom fantom[1]; |
86 |
|
struct vsc_head *head; |
87 |
|
char *body; |
88 |
|
|
89 |
|
struct vjsn *vj; |
90 |
|
|
91 |
|
unsigned npoints; |
92 |
|
struct vsc_pt *points; |
93 |
|
int exposed; |
94 |
|
}; |
95 |
|
|
96 |
|
struct vsc { |
97 |
|
unsigned magic; |
98 |
|
#define VSC_MAGIC 0x3373554a |
99 |
|
|
100 |
|
unsigned raw; |
101 |
|
struct vsc_sf_head sf_list; |
102 |
|
VTAILQ_HEAD(,vsc_seg) segs; |
103 |
|
|
104 |
|
VSC_new_f *fnew; |
105 |
|
VSC_destroy_f *fdestroy; |
106 |
|
void *priv; |
107 |
|
}; |
108 |
|
|
109 |
|
/*-------------------------------------------------------------------- |
110 |
|
* Build the static level, type and point descriptions |
111 |
|
*/ |
112 |
|
|
113 |
|
enum vsc_levels { |
114 |
|
#define VSC_LEVEL_F(v,l,e,d) v, |
115 |
|
#include "tbl/vsc_levels.h" |
116 |
|
}; |
117 |
|
|
118 |
|
static const struct VSC_level_desc levels[] = { |
119 |
|
#define VSC_LEVEL_F(v,l,e,d) [v] = {#v, l, e, d}, |
120 |
|
#include "tbl/vsc_levels.h" |
121 |
|
}; |
122 |
|
|
123 |
|
static const ssize_t nlevels = sizeof(levels)/sizeof(*levels); |
124 |
|
|
125 |
|
/*--------------------------------------------------------------------*/ |
126 |
|
|
127 |
|
struct vsc * |
128 |
37400 |
VSC_New(void) |
129 |
|
{ |
130 |
|
struct vsc *vsc; |
131 |
|
|
132 |
37400 |
ALLOC_OBJ(vsc, VSC_MAGIC); |
133 |
37400 |
if (vsc == NULL) |
134 |
0 |
return (vsc); |
135 |
37400 |
VTAILQ_INIT(&vsc->sf_list); |
136 |
37400 |
VTAILQ_INIT(&vsc->segs); |
137 |
37400 |
return (vsc); |
138 |
37400 |
} |
139 |
|
|
140 |
|
/*--------------------------------------------------------------------*/ |
141 |
|
|
142 |
|
static int |
143 |
1440 |
vsc_sf_arg(struct vsc *vsc, const char *glob, const struct vsc_sf_mode *mode) |
144 |
|
{ |
145 |
|
struct vsc_sf *sf; |
146 |
|
|
147 |
1440 |
CHECK_OBJ_NOTNULL(vsc, VSC_MAGIC); |
148 |
1440 |
AN(glob); |
149 |
1440 |
AN(mode); |
150 |
|
|
151 |
1440 |
ALLOC_OBJ(sf, VSC_SF_MAGIC); |
152 |
1440 |
AN(sf); |
153 |
1440 |
REPLACE(sf->pattern, glob); |
154 |
1440 |
sf->mode = mode; |
155 |
1440 |
AN(mode->name); |
156 |
1440 |
if (mode->append) |
157 |
1120 |
VTAILQ_INSERT_TAIL(&vsc->sf_list, sf, list); |
158 |
|
else |
159 |
320 |
VTAILQ_INSERT_HEAD(&vsc->sf_list, sf, list); |
160 |
1440 |
return (1); |
161 |
|
} |
162 |
|
|
163 |
|
static int |
164 |
800 |
vsc_f_arg(struct vsc *vsc, const char *opt) |
165 |
|
{ |
166 |
|
|
167 |
800 |
CHECK_OBJ_NOTNULL(vsc, VSC_MAGIC); |
168 |
800 |
AN(opt); |
169 |
|
|
170 |
800 |
if (opt[0] == '^') |
171 |
200 |
return (vsc_sf_arg(vsc, opt + 1, VSC_SF_EXCLUDE)); |
172 |
600 |
return (vsc_sf_arg(vsc, opt, VSC_SF_INCLUDE)); |
173 |
800 |
} |
174 |
|
|
175 |
|
/*--------------------------------------------------------------------*/ |
176 |
|
|
177 |
|
int |
178 |
1440 |
VSC_Arg(struct vsc *vsc, char arg, const char *opt) |
179 |
|
{ |
180 |
|
|
181 |
1440 |
CHECK_OBJ_NOTNULL(vsc, VSC_MAGIC); |
182 |
|
|
183 |
1440 |
switch (arg) { |
184 |
280 |
case 'I': return (vsc_sf_arg(vsc, opt, VSC_SF_INCLUDE)); |
185 |
40 |
case 'X': return (vsc_sf_arg(vsc, opt, VSC_SF_EXCLUDE)); |
186 |
320 |
case 'R': return (vsc_sf_arg(vsc, opt, VSC_SF_REQUIRE)); |
187 |
800 |
case 'f': return (vsc_f_arg(vsc, opt)); |
188 |
0 |
case 'r': vsc->raw = !vsc->raw; return (1); |
189 |
0 |
default: return (0); |
190 |
|
} |
191 |
1440 |
} |
192 |
|
|
193 |
|
unsigned |
194 |
240 |
VSC_IsRaw(const struct vsc *vsc) |
195 |
|
{ |
196 |
|
|
197 |
240 |
CHECK_OBJ_NOTNULL(vsc, VSC_MAGIC); |
198 |
240 |
return (vsc->raw); |
199 |
|
} |
200 |
|
|
201 |
|
/*-------------------------------------------------------------------- |
202 |
|
*/ |
203 |
|
|
204 |
|
static int |
205 |
2152272 |
vsc_filter(const struct vsc *vsc, const char *nm) |
206 |
|
{ |
207 |
|
struct vsc_sf *sf; |
208 |
2152272 |
unsigned res = 0; |
209 |
|
|
210 |
2152272 |
CHECK_OBJ_NOTNULL(vsc, VSC_MAGIC); |
211 |
2576392 |
VTAILQ_FOREACH(sf, &vsc->sf_list, list) { |
212 |
432040 |
if (!fnmatch(sf->pattern, nm, 0)) |
213 |
7920 |
return (!sf->mode->include); |
214 |
424120 |
res |= sf->mode->fail; |
215 |
424120 |
} |
216 |
2144352 |
return (res); |
217 |
2152272 |
} |
218 |
|
|
219 |
|
/*-------------------------------------------------------------------- |
220 |
|
*/ |
221 |
|
|
222 |
|
static void |
223 |
1860672 |
vsc_clean_point(struct vsc_pt *point) |
224 |
|
{ |
225 |
1860672 |
REPLACE(point->name, NULL); |
226 |
1860672 |
} |
227 |
|
|
228 |
|
static void |
229 |
2152272 |
vsc_fill_point(const struct vsc *vsc, const struct vsc_seg *seg, |
230 |
|
const struct vjsn_val *vv, struct vsb *vsb, struct vsc_pt *point) |
231 |
|
{ |
232 |
|
struct vjsn_val *vt; |
233 |
|
|
234 |
2152272 |
CHECK_OBJ_NOTNULL(vsc, VSC_MAGIC); |
235 |
2152272 |
memset(point, 0, sizeof *point); |
236 |
|
|
237 |
2152272 |
vt = vjsn_child(vv, "name"); |
238 |
2152272 |
AN(vt); |
239 |
2152272 |
assert(vjsn_is_string(vt)); |
240 |
|
|
241 |
2152272 |
VSB_clear(vsb); |
242 |
2152272 |
VSB_printf(vsb, "%s.%s", seg->fantom->ident, vt->value); |
243 |
2152272 |
AZ(VSB_finish(vsb)); |
244 |
|
|
245 |
2152272 |
if (vsc_filter(vsc, VSB_data(vsb))) |
246 |
144160 |
return; |
247 |
|
|
248 |
2008112 |
point->name = strdup(VSB_data(vsb)); |
249 |
2008112 |
AN(point->name); |
250 |
2008112 |
point->point.name = point->name; |
251 |
|
|
252 |
|
#define DOF(n, k) \ |
253 |
|
vt = vjsn_child(vv, k); \ |
254 |
|
AN(vt); \ |
255 |
|
assert(vjsn_is_string(vt)); \ |
256 |
|
point->point.n = vt->value; |
257 |
|
|
258 |
2008112 |
DOF(ctype, "ctype"); |
259 |
2008112 |
DOF(sdesc, "oneliner"); |
260 |
2008112 |
DOF(ldesc, "docs"); |
261 |
|
#undef DOF |
262 |
2008112 |
vt = vjsn_child(vv, "type"); |
263 |
2008112 |
AN(vt); |
264 |
2008112 |
assert(vjsn_is_string(vt)); |
265 |
|
|
266 |
2008112 |
if (!strcmp(vt->value, "counter")) { |
267 |
1747092 |
point->point.semantics = 'c'; |
268 |
2008112 |
} else if (!strcmp(vt->value, "gauge")) { |
269 |
254229 |
point->point.semantics = 'g'; |
270 |
261020 |
} else if (!strcmp(vt->value, "bitmap")) { |
271 |
6791 |
point->point.semantics = 'b'; |
272 |
6791 |
} else { |
273 |
0 |
point->point.semantics = '?'; |
274 |
|
} |
275 |
|
|
276 |
2008112 |
vt = vjsn_child(vv, "format"); |
277 |
2008112 |
AN(vt); |
278 |
2008112 |
assert(vjsn_is_string(vt)); |
279 |
|
|
280 |
2008112 |
if (!strcmp(vt->value, "integer")) { |
281 |
1784870 |
point->point.format = 'i'; |
282 |
2008112 |
} else if (!strcmp(vt->value, "bytes")) { |
283 |
199251 |
point->point.format = 'B'; |
284 |
223242 |
} else if (!strcmp(vt->value, "bitmap")) { |
285 |
6791 |
point->point.format = 'b'; |
286 |
23991 |
} else if (!strcmp(vt->value, "duration")) { |
287 |
17200 |
point->point.format = 'd'; |
288 |
17200 |
} else { |
289 |
0 |
point->point.format = '?'; |
290 |
|
} |
291 |
|
|
292 |
2008112 |
vt = vjsn_child(vv, "level"); |
293 |
2008112 |
AN(vt); |
294 |
2008112 |
assert(vjsn_is_string(vt)); |
295 |
|
|
296 |
2008112 |
if (!strcmp(vt->value, "info")) { |
297 |
925917 |
point->point.level = &levels[info]; |
298 |
2008112 |
} else if (!strcmp(vt->value, "diag")) { |
299 |
567577 |
point->point.level = &levels[diag]; |
300 |
1082195 |
} else if (!strcmp(vt->value, "debug")) { |
301 |
514618 |
point->point.level = &levels[debug]; |
302 |
514618 |
} else { |
303 |
0 |
WRONG("Illegal level"); |
304 |
|
} |
305 |
|
|
306 |
2008112 |
vt = vjsn_child(vv, "index"); |
307 |
2008112 |
AN(vt); |
308 |
|
|
309 |
2008112 |
point->point.ptr = (volatile void*)(seg->body + atoi(vt->value)); |
310 |
2008112 |
point->point.raw = vsc->raw; |
311 |
2152272 |
} |
312 |
|
|
313 |
|
static void |
314 |
125399 |
vsc_del_seg(const struct vsc *vsc, struct vsm *vsm, struct vsc_seg **spp) |
315 |
|
{ |
316 |
|
unsigned u; |
317 |
|
struct vsc_pt *pp; |
318 |
|
struct vsc_seg *sp; |
319 |
|
|
320 |
125399 |
CHECK_OBJ_NOTNULL(vsc, VSC_MAGIC); |
321 |
125399 |
TAKE_OBJ_NOTNULL(sp, spp, VSC_SEG_MAGIC); |
322 |
125399 |
AZ(VSM_Unmap(vsm, sp->fantom)); |
323 |
125399 |
if (sp->vj != NULL) { |
324 |
27982 |
vjsn_delete(&sp->vj); |
325 |
27982 |
} else { |
326 |
97417 |
pp = sp->points; |
327 |
1958089 |
for (u = 0; u < sp->npoints; u++, pp++) |
328 |
1860672 |
vsc_clean_point(pp); |
329 |
97417 |
free(sp->points); |
330 |
|
} |
331 |
125399 |
FREE_OBJ(sp); |
332 |
125399 |
} |
333 |
|
|
334 |
|
static struct vsc_seg * |
335 |
152159 |
vsc_add_seg(const struct vsc *vsc, struct vsm *vsm, const struct vsm_fantom *fp) |
336 |
|
{ |
337 |
|
struct vsc_seg *sp, *spd; |
338 |
|
const char *e; |
339 |
|
struct vjsn_val *vv, *vve; |
340 |
|
struct vsb *vsb; |
341 |
|
struct vsc_pt *pp; |
342 |
|
|
343 |
152159 |
CHECK_OBJ_NOTNULL(vsc, VSC_MAGIC); |
344 |
|
|
345 |
152159 |
ALLOC_OBJ(sp, VSC_SEG_MAGIC); |
346 |
152159 |
AN(sp); |
347 |
152159 |
*sp->fantom = *fp; |
348 |
152159 |
if (VSM_Map(vsm, sp->fantom)) { |
349 |
|
/* |
350 |
|
* If the seg was removed between our call to VSM_Status() |
351 |
|
* and now, we won't be able to map it. |
352 |
|
*/ |
353 |
0 |
FREE_OBJ(sp); |
354 |
0 |
return (NULL); |
355 |
|
} |
356 |
152159 |
sp->head = sp->fantom->b; |
357 |
152159 |
if (sp->head->ready == 0) { |
358 |
0 |
VRMB(); |
359 |
0 |
usleep(100000); |
360 |
0 |
} |
361 |
152159 |
assert(sp->head->ready > 0); |
362 |
152159 |
sp->body = (char*)sp->fantom->b + sp->head->body_offset; |
363 |
|
|
364 |
152159 |
if (!strcmp(fp->category, VSC_CLASS)) { |
365 |
1368406 |
VTAILQ_FOREACH(spd, &vsc->segs, list) |
366 |
1368406 |
if (spd->head->doc_id == sp->head->doc_id) |
367 |
120577 |
break; |
368 |
120577 |
AN(spd); |
369 |
|
// XXX: Refcount ? |
370 |
120577 |
vve = vjsn_child(spd->vj->value, "elements"); |
371 |
120577 |
AN(vve); |
372 |
120577 |
sp->npoints = strtoul(vve->value, NULL, 0); |
373 |
120577 |
sp->points = calloc(sp->npoints, sizeof *sp->points); |
374 |
120577 |
AN(sp->points); |
375 |
120577 |
vsb = VSB_new_auto(); |
376 |
120577 |
AN(vsb); |
377 |
120577 |
vve = vjsn_child(spd->vj->value, "elem"); |
378 |
120577 |
AN(vve); |
379 |
120577 |
pp = sp->points; |
380 |
2272849 |
VTAILQ_FOREACH(vv, &vve->children, list) { |
381 |
2152272 |
vsc_fill_point(vsc, sp, vv, vsb, pp); |
382 |
2152272 |
pp++; |
383 |
2152272 |
} |
384 |
120577 |
VSB_destroy(&vsb); |
385 |
120577 |
return (sp); |
386 |
|
} |
387 |
31582 |
assert(!strcmp(fp->category, VSC_DOC_CLASS)); |
388 |
31582 |
sp->vj = vjsn_parse(sp->body, &e); |
389 |
31582 |
XXXAZ(e); |
390 |
31582 |
AN(sp->vj); |
391 |
31582 |
return (sp); |
392 |
152159 |
} |
393 |
|
|
394 |
|
/*-------------------------------------------------------------------- |
395 |
|
*/ |
396 |
|
|
397 |
|
static void |
398 |
1067063 |
vsc_expose(const struct vsc *vsc, struct vsc_seg *sp, int del) |
399 |
|
{ |
400 |
|
struct vsc_pt *pp; |
401 |
|
unsigned u; |
402 |
|
int expose; |
403 |
|
|
404 |
1076023 |
if (vsc->fnew != NULL && !sp->exposed && |
405 |
8960 |
!del && sp->head->ready == 1) |
406 |
8960 |
expose = 1; |
407 |
1125609 |
else if (vsc->fdestroy != NULL && sp->exposed && |
408 |
76466 |
(del || sp->head->ready == 2)) |
409 |
8960 |
expose = 0; |
410 |
|
else |
411 |
1049143 |
return; |
412 |
|
|
413 |
17920 |
pp = sp->points; |
414 |
184640 |
for (u = 0; u < sp->npoints; u++, pp++) { |
415 |
166720 |
if (pp->name == NULL) |
416 |
26320 |
continue; |
417 |
140400 |
if (expose) |
418 |
70200 |
pp->point.priv = vsc->fnew(vsc->priv, &pp->point); |
419 |
|
else |
420 |
70200 |
vsc->fdestroy(vsc->priv, &pp->point); |
421 |
140400 |
} |
422 |
17920 |
sp->exposed = expose; |
423 |
1067063 |
} |
424 |
|
|
425 |
|
/*-------------------------------------------------------------------- |
426 |
|
*/ |
427 |
|
|
428 |
|
static int |
429 |
857158 |
vsc_iter_seg(const struct vsc *vsc, const struct vsc_seg *sp, |
430 |
|
VSC_iter_f *fiter, void *priv) |
431 |
|
{ |
432 |
|
unsigned u; |
433 |
857158 |
int i = 0; |
434 |
|
struct vsc_pt *pp; |
435 |
|
|
436 |
857158 |
CHECK_OBJ_NOTNULL(vsc, VSC_MAGIC); |
437 |
857158 |
CHECK_OBJ_NOTNULL(sp, VSC_SEG_MAGIC); |
438 |
857158 |
AN(fiter); |
439 |
857158 |
pp = sp->points; |
440 |
10046846 |
for (u = 0; u < sp->npoints && i == 0; u++, pp++) { |
441 |
9189688 |
if (pp->name != NULL) |
442 |
9111248 |
i = fiter(priv, &pp->point); |
443 |
9189688 |
} |
444 |
857158 |
return (i); |
445 |
|
} |
446 |
|
|
447 |
|
int |
448 |
46379 |
VSC_Iter(struct vsc *vsc, struct vsm *vsm, VSC_iter_f *fiter, void *priv) |
449 |
|
{ |
450 |
|
struct vsm_fantom ifantom; |
451 |
|
struct vsc_seg *sp, *sp2; |
452 |
46379 |
int i = 0; |
453 |
|
|
454 |
46379 |
CHECK_OBJ_NOTNULL(vsc, VSC_MAGIC); |
455 |
46379 |
AN(vsm); |
456 |
46379 |
sp = VTAILQ_FIRST(&vsc->segs); |
457 |
1208964 |
VSM_FOREACH(&ifantom, vsm) { |
458 |
1195937 |
AN(ifantom.category); |
459 |
1195937 |
if (strcmp(ifantom.category, VSC_CLASS) && |
460 |
429345 |
strcmp(ifantom.category, VSC_DOC_CLASS)) |
461 |
254273 |
continue; |
462 |
1740215 |
while (sp != NULL && |
463 |
794028 |
(strcmp(ifantom.ident, sp->fantom->ident) || |
464 |
790025 |
VSM_StillValid(vsm, sp->fantom) != VSM_valid)) { |
465 |
4523 |
sp2 = sp; |
466 |
4523 |
sp = VTAILQ_NEXT(sp, list); |
467 |
4523 |
VTAILQ_REMOVE(&vsc->segs, sp2, list); |
468 |
4523 |
vsc_expose(vsc, sp2, 1); |
469 |
4523 |
vsc_del_seg(vsc, vsm, &sp2); |
470 |
|
} |
471 |
941664 |
if (sp == NULL) { |
472 |
152159 |
sp = vsc_add_seg(vsc, vsm, &ifantom); |
473 |
152159 |
if (sp != NULL) { |
474 |
152159 |
VTAILQ_INSERT_TAIL(&vsc->segs, sp, list); |
475 |
152159 |
vsc_expose(vsc, sp, 0); |
476 |
152159 |
} |
477 |
152159 |
} else { |
478 |
789505 |
vsc_expose(vsc, sp, 0); |
479 |
|
} |
480 |
941664 |
if (sp != NULL) { |
481 |
941664 |
if (fiter != NULL && sp->head->ready < 2) |
482 |
857158 |
i = vsc_iter_seg(vsc, sp, fiter, priv); |
483 |
941664 |
sp = VTAILQ_NEXT(sp, list); |
484 |
941664 |
} |
485 |
|
|
486 |
941664 |
if (i) |
487 |
33352 |
break; |
488 |
|
} |
489 |
84895 |
while (sp != NULL) { |
490 |
38516 |
sp2 = sp; |
491 |
38516 |
sp = VTAILQ_NEXT(sp, list); |
492 |
38516 |
VTAILQ_REMOVE(&vsc->segs, sp2, list); |
493 |
38516 |
vsc_expose(vsc, sp2, 1); |
494 |
38516 |
vsc_del_seg(vsc, vsm, &sp2); |
495 |
|
} |
496 |
46379 |
return (i); |
497 |
|
} |
498 |
|
|
499 |
|
/*-------------------------------------------------------------------- |
500 |
|
*/ |
501 |
|
|
502 |
|
void |
503 |
240 |
VSC_State(struct vsc *vsc, VSC_new_f *fn, VSC_destroy_f *fd, void *priv) |
504 |
|
{ |
505 |
|
struct vsc_seg *sp; |
506 |
|
|
507 |
240 |
CHECK_OBJ_NOTNULL(vsc, VSC_MAGIC); |
508 |
240 |
assert((fn == NULL && fd == NULL) || (fn != NULL && fd != NULL)); |
509 |
240 |
if (fd == NULL) { |
510 |
0 |
VTAILQ_FOREACH(sp, &vsc->segs, list) |
511 |
0 |
vsc_expose(vsc, sp, 1); |
512 |
0 |
} |
513 |
240 |
vsc->fnew = fn; |
514 |
240 |
vsc->fdestroy = fd; |
515 |
240 |
vsc->priv = priv; |
516 |
240 |
} |
517 |
|
|
518 |
|
/*-------------------------------------------------------------------- |
519 |
|
*/ |
520 |
|
|
521 |
|
const struct VSC_level_desc * |
522 |
400 |
VSC_ChangeLevel(const struct VSC_level_desc *old, int chg) |
523 |
|
{ |
524 |
|
int i; |
525 |
|
|
526 |
400 |
if (old == NULL) |
527 |
240 |
old = &levels[0]; |
528 |
440 |
for (i = 0; i < nlevels; i++) |
529 |
440 |
if (old == &levels[i]) |
530 |
400 |
break; |
531 |
400 |
if (i == nlevels) |
532 |
0 |
i = 0; |
533 |
|
|
534 |
400 |
i += chg; |
535 |
400 |
if (i >= nlevels) |
536 |
0 |
i = nlevels - 1; |
537 |
400 |
if (i < 0) |
538 |
0 |
i = 0; |
539 |
400 |
return (&levels[i]); |
540 |
|
} |
541 |
|
|
542 |
|
/*--------------------------------------------------------------------*/ |
543 |
|
|
544 |
|
void |
545 |
36520 |
VSC_Destroy(struct vsc **vscp, struct vsm *vsm) |
546 |
|
{ |
547 |
|
struct vsc *vsc; |
548 |
|
struct vsc_sf *sf, *sf2; |
549 |
|
struct vsc_seg *sp, *sp2; |
550 |
|
|
551 |
36520 |
TAKE_OBJ_NOTNULL(vsc, vscp, VSC_MAGIC); |
552 |
|
|
553 |
37280 |
VTAILQ_FOREACH_SAFE(sf, &vsc->sf_list, list, sf2) { |
554 |
760 |
CHECK_OBJ_NOTNULL(sf, VSC_SF_MAGIC); |
555 |
760 |
VTAILQ_REMOVE(&vsc->sf_list, sf, list); |
556 |
760 |
free(sf->pattern); |
557 |
760 |
FREE_OBJ(sf); |
558 |
760 |
} |
559 |
118880 |
VTAILQ_FOREACH_SAFE(sp, &vsc->segs, list, sp2) { |
560 |
82360 |
VTAILQ_REMOVE(&vsc->segs, sp, list); |
561 |
82360 |
vsc_expose(vsc, sp, 1); |
562 |
82360 |
vsc_del_seg(vsc, vsm, &sp); |
563 |
82360 |
} |
564 |
36520 |
FREE_OBJ(vsc); |
565 |
36520 |
} |
566 |
|
|