varnish-cache/bin/varnishd/storage/storage_simple.c
0
/*-
1
 * Copyright (c) 2007-2015 Varnish Software AS
2
 * All rights reserved.
3
 *
4
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
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
 */
30
31
#include "config.h"
32
33
#include "cache/cache_varnishd.h"
34
35 187900
#include "cache/cache_obj.h"
36 115847
#include "cache/cache_objhead.h"
37 182944
38 11027
#include "storage/storage.h"
39 52871
#include "storage/storage_simple.h"
40
41
#include "vtim.h"
42
43
/* Flags for allocating memory in sml_stv_alloc */
44
#define LESS_MEM_ALLOCED_IS_OK  1
45 79650
46 188819
// marker pointer for sml_trimstore
47
static void *trim_once = &trim_once;
48
49
/*-------------------------------------------------------------------*/
50
51
static struct storage *
52 84536
objallocwithnuke(struct worker *, const struct stevedore *, ssize_t size,
53
    int flags);
54
55
static struct storage *
56 74637
sml_stv_alloc(const struct stevedore *stv, ssize_t size, int flags)
57
{
58
        struct storage *st;
59
60 74637
        CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);
61 74637
        AN(stv->sml_alloc);
62
63 74637
        if (!(flags & LESS_MEM_ALLOCED_IS_OK)) {
64 8452
                if (size > cache_param->fetch_maxchunksize)
65 0
                        return (NULL);
66
                else
67 8452
                        return (stv->sml_alloc(stv, size));
68
        }
69
70 66185
        if (size > cache_param->fetch_maxchunksize)
71 0
                size = cache_param->fetch_maxchunksize;
72
73 66185
        assert(size <= UINT_MAX);       /* field limit in struct storage */
74
75 69560
        for (;;) {
76
                /* try to allocate from it */
77 69560
                assert(size > 0);
78 69560
                st = stv->sml_alloc(stv, size);
79 69560
                if (st != NULL)
80 65910
                        break;
81
82 3650
                if (size <= cache_param->fetch_chunksize)
83 275
                        break;
84
85 3375
                size /= 2;
86
        }
87 66185
        CHECK_OBJ_ORNULL(st, STORAGE_MAGIC);
88 66185
        return (st);
89 74637
}
90
91
static void
92 95674
sml_stv_free(const struct stevedore *stv, struct storage *st)
93
{
94
95 95674
        CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);
96 95674
        CHECK_OBJ_NOTNULL(st, STORAGE_MAGIC);
97 95674
        if (stv->sml_free != NULL)
98 95674
                stv->sml_free(st);
99 95674
}
100
101
/*--------------------------------------------------------------------
102
 * This function is called by stevedores ->allocobj() method, which
103
 * very often will be SML_allocobj() below, to convert a slab
104
 * of storage into object which the stevedore can then register in its
105
 * internal state, before returning it to STV_NewObject().
106
 * As you probably guessed: All this for persistence.
107
 */
108
109
struct object *
110 65998
SML_MkObject(const struct stevedore *stv, struct objcore *oc, void *ptr)
111
{
112
        struct object *o;
113
114 65998
        CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);
115 65998
        AN(stv->methods);
116 65998
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
117
118 65998
        assert(PAOK(ptr));
119
120 65998
        o = ptr;
121 65998
        INIT_OBJ(o, OBJECT_MAGIC);
122
123 65998
        VTAILQ_INIT(&o->list);
124
125 65998
        oc->stobj->stevedore = stv;
126 65998
        oc->stobj->priv = o;
127 65998
        oc->stobj->priv2 = 0;
128 65998
        return (o);
129
}
130
131
/*--------------------------------------------------------------------
132
 * This is the default ->allocobj() which all stevedores who do not
133
 * implement persistent storage can rely on.
134
 */
135
136
int v_matchproto_(storage_allocobj_f)
137 65723
SML_allocobj(struct worker *wrk, const struct stevedore *stv,
138
    struct objcore *oc, unsigned wsl)
139
{
140
        struct object *o;
141 65723
        struct storage *st = NULL;
142
        unsigned ltot;
143
144 65723
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
145 65723
        CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);
146 65723
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
147
148 65723
        AN(stv->sml_alloc);
149
150 65723
        ltot = sizeof(*o) + PRNDUP(wsl);
151
152 65723
        do {
153 65798
                st = stv->sml_alloc(stv, ltot);
154 65798
                if (st != NULL && st->space < ltot) {
155 0
                        stv->sml_free(st);
156 0
                        st = NULL;
157 0
                }
158 65798
        } while (st == NULL && LRU_NukeOne(wrk, stv->lru));
159 65723
        if (st == NULL)
160 275
                return (0);
161
162 65448
        CHECK_OBJ_NOTNULL(st, STORAGE_MAGIC);
163 65448
        o = SML_MkObject(stv, oc, st->ptr);
164 65448
        CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
165 65448
        st->len = sizeof(*o);
166 65448
        o->objstore = st;
167 65448
        return (1);
168 65723
}
169
170
void * v_matchproto_(storage_allocbuf_t)
171 550
SML_AllocBuf(struct worker *wrk, const struct stevedore *stv, size_t size,
172
    uintptr_t *ppriv)
173
{
174
        struct storage *st;
175
176 550
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
177 550
        CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);
178 550
        AN(ppriv);
179
180 550
        if (size > UINT_MAX)
181 0
                return (NULL);
182 550
        st = objallocwithnuke(wrk, stv, size, 0);
183 550
        if (st == NULL)
184 0
                return (NULL);
185 550
        assert(st->space >= size);
186 550
        st->len = size;
187 550
        *ppriv = (uintptr_t)st;
188 550
        return (st->ptr);
189 550
}
190
191
void v_matchproto_(storage_freebuf_t)
192 550
SML_FreeBuf(struct worker *wrk, const struct stevedore *stv, uintptr_t priv)
193
{
194
        struct storage *st;
195
196 550
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
197 550
        CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);
198
199 550
        CAST_OBJ_NOTNULL(st, (void *)priv, STORAGE_MAGIC);
200 550
        sml_stv_free(stv, st);
201 550
}
202
203
/*---------------------------------------------------------------------
204
 */
205
206
static struct object *
207 3802403
sml_getobj(struct worker *wrk, struct objcore *oc)
208
{
209
        const struct stevedore *stv;
210
        struct object *o;
211
212 3802403
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
213 3802403
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
214 3802403
        stv = oc->stobj->stevedore;
215 3802403
        CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);
216 3802403
        if (stv->sml_getobj != NULL)
217 7250
                return (stv->sml_getobj(wrk, oc));
218 3795153
        if (oc->stobj->priv == NULL)
219 0
                return (NULL);
220 3795153
        CAST_OBJ_NOTNULL(o, oc->stobj->priv, OBJECT_MAGIC);
221 3795153
        return (o);
222 3802403
}
223
224
static void v_matchproto_(objslim_f)
225 76336
sml_slim(struct worker *wrk, struct objcore *oc)
226
{
227
        const struct stevedore *stv;
228
        struct object *o;
229
        struct storage *st, *stn;
230
231 76336
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
232
233 76336
        stv = oc->stobj->stevedore;
234 76336
        CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);
235 76336
        o = sml_getobj(wrk, oc);
236 76336
        CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
237
238
#define OBJ_AUXATTR(U, l)                                       \
239
        do {                                                    \
240
                if (o->aa_##l != NULL) {                        \
241
                        sml_stv_free(stv, o->aa_##l);           \
242
                        o->aa_##l = NULL;                       \
243
                }                                               \
244
        } while (0);
245
#include "tbl/obj_attr.h"
246
247 96425
        VTAILQ_FOREACH_SAFE(st, &o->list, list, stn) {
248 20089
                CHECK_OBJ_NOTNULL(st, STORAGE_MAGIC);
249 20089
                VTAILQ_REMOVE(&o->list, st, list);
250 20089
                sml_stv_free(stv, st);
251 20089
        }
252 76336
}
253
254
static void
255 66398
sml_bocfini(const struct stevedore *stv, struct boc *boc)
256
{
257
        struct storage *st;
258
259 66398
        CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);
260 66398
        CHECK_OBJ_NOTNULL(boc, BOC_MAGIC);
261
262 66398
        if (boc->stevedore_priv == NULL ||
263 43526
            boc->stevedore_priv == trim_once)
264 61396
                return;
265
266
        /* Free any leftovers from Trim */
267 5002
        TAKE_OBJ_NOTNULL(st, &boc->stevedore_priv, STORAGE_MAGIC);
268 5002
        sml_stv_free(stv, st);
269 66398
}
270
271
/*
272
 * called in two cases:
273
 * - oc->boc == NULL: cache object on LRU freed
274
 * - oc->boc != NULL: cache object replaced for backend error
275
 */
276
static void v_matchproto_(objfree_f)
277 40714
sml_objfree(struct worker *wrk, struct objcore *oc)
278
{
279
        const struct stevedore *stv;
280
        struct storage *st;
281
        struct object *o;
282
283 40714
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
284 40714
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
285 40714
        stv = oc->stobj->stevedore;
286 40714
        CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);
287 40714
        CAST_OBJ_NOTNULL(o, oc->stobj->priv, OBJECT_MAGIC);
288
289 40714
        sml_slim(wrk, oc);
290 40714
        st = o->objstore;
291 40714
        CHECK_OBJ_NOTNULL(st, STORAGE_MAGIC);
292 40714
        FINI_OBJ(o);
293
294 40714
        if (oc->boc != NULL)
295 525
                sml_bocfini(stv, oc->boc);
296 40189
        else if (stv->lru != NULL)
297 40189
                LRU_Remove(oc);
298
299 40714
        sml_stv_free(stv, st);
300
301 40714
        memset(oc->stobj, 0, sizeof oc->stobj);
302
303 40714
        wrk->stats->n_object--;
304 40714
}
305
306
static int v_matchproto_(objiterator_f)
307 55716
sml_iterator(struct worker *wrk, struct objcore *oc,
308
    void *priv, objiterate_f *func, int final)
309
{
310
        struct boc *boc;
311
        enum boc_state_e state;
312
        struct object *obj;
313
        struct storage *st;
314 55716
        struct storage *checkpoint = NULL;
315
        const struct stevedore *stv;
316 55716
        ssize_t checkpoint_len = 0;
317 55716
        ssize_t len = 0;
318 55716
        int ret = 0, ret2;
319
        ssize_t ol;
320
        ssize_t nl;
321
        ssize_t sl;
322
        void *p;
323
        ssize_t l;
324
        unsigned u;
325
326 55716
        obj = sml_getobj(wrk, oc);
327 55716
        CHECK_OBJ_NOTNULL(obj, OBJECT_MAGIC);
328 55716
        stv = oc->stobj->stevedore;
329 55716
        CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);
330
331 55716
        boc = HSH_RefBoc(oc);
332
333 55716
        if (boc == NULL) {
334 78055
                VTAILQ_FOREACH_REVERSE_SAFE(
335
                    st, &obj->list, storagehead, list, checkpoint) {
336
337 41591
                        u = 0;
338 41591
                        if (VTAILQ_PREV(st, storagehead, list) == NULL)
339 37212
                                u |= OBJ_ITER_END;
340 41591
                        if (final)
341 16441
                                u |= OBJ_ITER_FLUSH;
342 41591
                        if (ret == 0 && st->len > 0)
343 41586
                                ret = func(priv, u, st->ptr, st->len);
344 41595
                        if (final) {
345 16442
                                VTAILQ_REMOVE(&obj->list, st, list);
346 16442
                                sml_stv_free(stv, st);
347 41589
                        } else if (ret)
348 775
                                break;
349 40814
                }
350 37239
                return (ret);
351
        }
352
353 18475
        p = NULL;
354 18475
        l = 0;
355
356 18475
        u = 0;
357 18475
        if (boc->fetched_so_far == 0) {
358 2053
                ret = func(priv, OBJ_ITER_FLUSH, NULL, 0);
359 2053
                if (ret)
360 0
                        return (ret);
361 2053
        }
362 53867
        while (1) {
363 53867
                ol = len;
364 53867
                nl = ObjWaitExtend(wrk, oc, ol);
365 53867
                if (boc->state == BOS_FAILED) {
366 350
                        ret = -1;
367 350
                        break;
368
                }
369 53517
                if (nl == ol) {
370 17685
                        if (boc->state == BOS_FINISHED)
371 17685
                                break;
372 0
                        continue;
373
                }
374 35832
                Lck_Lock(&boc->mtx);
375 35832
                AZ(VTAILQ_EMPTY(&obj->list));
376 35832
                if (checkpoint == NULL) {
377 22089
                        st = VTAILQ_LAST(&obj->list, storagehead);
378 22089
                        sl = 0;
379 22089
                } else {
380 13743
                        st = checkpoint;
381 13743
                        sl = checkpoint_len;
382 13743
                        ol -= checkpoint_len;
383
                }
384 56125
                while (st != NULL) {
385 56128
                        if (st->len > ol) {
386 35835
                                p = st->ptr + ol;
387 35835
                                l = st->len - ol;
388 35835
                                len += l;
389 35835
                                break;
390
                        }
391 20293
                        ol -= st->len;
392 20293
                        assert(ol >= 0);
393 20293
                        nl -= st->len;
394 20293
                        assert(nl > 0);
395 20293
                        sl += st->len;
396 20293
                        st = VTAILQ_PREV(st, storagehead, list);
397 20293
                        if (VTAILQ_PREV(st, storagehead, list) != NULL) {
398 13139
                                if (final && checkpoint != NULL) {
399 12379
                                        VTAILQ_REMOVE(&obj->list,
400
                                            checkpoint, list);
401 12379
                                        sml_stv_free(stv, checkpoint);
402 12379
                                }
403 13139
                                checkpoint = st;
404 13139
                                checkpoint_len = sl;
405 13139
                        }
406
                }
407 35840
                CHECK_OBJ_NOTNULL(obj, OBJECT_MAGIC);
408 35840
                CHECK_OBJ_NOTNULL(st, STORAGE_MAGIC);
409 35840
                st = VTAILQ_PREV(st, storagehead, list);
410 35840
                if (st != NULL && st->len == 0)
411 6092
                        st = NULL;
412 35840
                state = boc->state;
413 35840
                Lck_Unlock(&boc->mtx);
414 35840
                assert(l > 0 || state == BOS_FINISHED);
415 35840
                u = 0;
416 35840
                if (st == NULL || final)
417 35365
                        u |= OBJ_ITER_FLUSH;
418 35840
                if (st == NULL && state == BOS_FINISHED)
419 183
                        u |= OBJ_ITER_END;
420 35840
                ret = func(priv, u, p, l);
421 35840
                if (ret)
422 448
                        break;
423
        }
424 18483
        HSH_DerefBoc(wrk, oc);
425 18483
        if ((u & OBJ_ITER_END) == 0) {
426 18299
                ret2 = func(priv, OBJ_ITER_END, NULL, 0);
427 18299
                if (ret == 0)
428 17501
                        ret = ret2;
429 18299
        }
430 18483
        return (ret);
431 55722
}
432
433
/*--------------------------------------------------------------------
434
 */
435
436
static struct storage *
437 69435
objallocwithnuke(struct worker *wrk, const struct stevedore *stv, ssize_t size,
438
    int flags)
439
{
440 69435
        struct storage *st = NULL;
441
442 69435
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
443 69435
        CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);
444
445 69435
        if (size > cache_param->fetch_maxchunksize) {
446 50
                if (!(flags & LESS_MEM_ALLOCED_IS_OK))
447 0
                        return (NULL);
448 50
                size = cache_param->fetch_maxchunksize;
449 50
        }
450
451 69435
        assert(size <= UINT_MAX);       /* field limit in struct storage */
452
453 69435
        do {
454
                /* try to allocate from it */
455 69635
                st = sml_stv_alloc(stv, size, flags);
456 69635
                if (st != NULL)
457 69310
                        break;
458
459
                /* no luck; try to free some space and keep trying */
460 325
                if (stv->lru == NULL)
461 0
                        break;
462 325
        } while (LRU_NukeOne(wrk, stv->lru));
463
464 69435
        CHECK_OBJ_ORNULL(st, STORAGE_MAGIC);
465 69435
        return (st);
466 69435
}
467
468
static int v_matchproto_(objgetspace_f)
469 1446994
sml_getspace(struct worker *wrk, struct objcore *oc, ssize_t *sz,
470
    uint8_t **ptr)
471
{
472
        struct object *o;
473
        struct storage *st;
474
475 1446994
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
476 1446994
        AN(sz);
477 1446994
        AN(ptr);
478 1446994
        if (*sz == 0)
479 1360936
                *sz = cache_param->fetch_chunksize;
480 1446994
        assert(*sz > 0);
481
482 1446994
        o = sml_getobj(wrk, oc);
483 1446994
        CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
484 1446994
        CHECK_OBJ_NOTNULL(oc->boc, BOC_MAGIC);
485
486 1446994
        st = VTAILQ_FIRST(&o->list);
487 1446994
        if (st != NULL && st->len < st->space) {
488 1380959
                *sz = st->space - st->len;
489 1380959
                *ptr = st->ptr + st->len;
490 1380959
                assert (*sz > 0);
491 1380959
                return (1);
492
        }
493
494 66035
        st = objallocwithnuke(wrk, oc->stobj->stevedore, *sz,
495
            LESS_MEM_ALLOCED_IS_OK);
496 66035
        if (st == NULL)
497 125
                return (0);
498
499 65910
        CHECK_OBJ_NOTNULL(oc->boc, BOC_MAGIC);
500 65910
        Lck_Lock(&oc->boc->mtx);
501 65910
        VTAILQ_INSERT_HEAD(&o->list, st, list);
502 65910
        Lck_Unlock(&oc->boc->mtx);
503
504 65910
        *sz = st->space - st->len;
505 65910
        assert (*sz > 0);
506 65910
        *ptr = st->ptr + st->len;
507 65910
        return (1);
508 1446994
}
509
510
static void v_matchproto_(objextend_f)
511 1410823
sml_extend(struct worker *wrk, struct objcore *oc, ssize_t l)
512
{
513
        struct object *o;
514
        struct storage *st;
515
516 1410823
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
517 1410823
        assert(l > 0);
518
519 1410823
        o = sml_getobj(wrk, oc);
520 1410823
        CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
521 1410823
        st = VTAILQ_FIRST(&o->list);
522 1410823
        CHECK_OBJ_NOTNULL(st, STORAGE_MAGIC);
523 1410823
        assert(st->len + l <= st->space);
524 1410823
        st->len += l;
525 1410823
}
526
527
static void v_matchproto_(objtrimstore_f)
528 43525
sml_trimstore(struct worker *wrk, struct objcore *oc)
529
{
530
        const struct stevedore *stv;
531
        struct storage *st, *st1;
532
        struct object *o;
533
534 43525
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
535 43525
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
536 43525
        CHECK_OBJ_NOTNULL(oc->boc, BOC_MAGIC);
537
538 43525
        stv = oc->stobj->stevedore;
539 43525
        CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);
540
541 43525
        if (oc->boc->stevedore_priv != NULL)
542 0
                WRONG("sml_trimstore already called");
543 43525
        oc->boc->stevedore_priv = trim_once;
544
545 43525
        if (stv->sml_free == NULL)
546 0
                return;
547
548 43525
        o = sml_getobj(wrk, oc);
549 43525
        CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
550 43525
        st = VTAILQ_FIRST(&o->list);
551
552 43525
        if (st == NULL)
553 0
                return;
554
555 43525
        if (st->len == 0) {
556 200
                Lck_Lock(&oc->boc->mtx);
557 200
                VTAILQ_REMOVE(&o->list, st, list);
558 200
                Lck_Unlock(&oc->boc->mtx);
559 200
                sml_stv_free(stv, st);
560 200
                return;
561
        }
562
563 43325
        if (st->space - st->len < 512)
564 38323
                return;
565
566 5002
        st1 = sml_stv_alloc(stv, st->len, 0);
567 5002
        if (st1 == NULL)
568 0
                return;
569 5002
        assert(st1->space >= st->len);
570
571 5002
        memcpy(st1->ptr, st->ptr, st->len);
572 5002
        st1->len = st->len;
573 5002
        Lck_Lock(&oc->boc->mtx);
574 5002
        VTAILQ_REMOVE(&o->list, st, list);
575 5002
        VTAILQ_INSERT_HEAD(&o->list, st1, list);
576 5002
        Lck_Unlock(&oc->boc->mtx);
577
        /* sml_bocdone frees this */
578 5002
        oc->boc->stevedore_priv = st;
579 43525
}
580
581
static void v_matchproto_(objbocdone_f)
582 65874
sml_bocdone(struct worker *wrk, struct objcore *oc, struct boc *boc)
583
{
584
        const struct stevedore *stv;
585
586 65874
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
587 65874
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
588 65874
        CHECK_OBJ_NOTNULL(boc, BOC_MAGIC);
589 65874
        stv = oc->stobj->stevedore;
590 65874
        CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);
591
592 65874
        sml_bocfini(stv, boc);
593
594 65874
        if (stv->lru != NULL) {
595 64897
                if (isnan(wrk->lastused))
596 0
                        wrk->lastused = VTIM_real();
597 64897
                LRU_Add(oc, wrk->lastused);     // approx timestamp is OK
598 64897
        }
599 65874
}
600
601
static const void * v_matchproto_(objgetattr_f)
602 518495
sml_getattr(struct worker *wrk, struct objcore *oc, enum obj_attr attr,
603
   ssize_t *len)
604
{
605
        struct object *o;
606
        ssize_t dummy;
607
608 518495
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
609
610 518495
        if (len == NULL)
611 322464
                len = &dummy;
612 518495
        o = sml_getobj(wrk, oc);
613 518495
        CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
614
615 518495
        switch (attr) {
616
                /* Fixed size attributes */
617
#define OBJ_FIXATTR(U, l, s)                                            \
618
        case OA_##U:                                                    \
619
                *len = sizeof o->fa_##l;                                \
620
                return (o->fa_##l);
621
#include "tbl/obj_attr.h"
622
623
                /* Variable size attributes */
624
#define OBJ_VARATTR(U, l)                                               \
625
        case OA_##U:                                                    \
626
                if (o->va_##l == NULL)                                  \
627
                        return (NULL);                                  \
628
                *len = o->va_##l##_len;                                 \
629
                return (o->va_##l);
630
#include "tbl/obj_attr.h"
631
632
                /* Auxiliary attributes */
633
#define OBJ_AUXATTR(U, l)                                               \
634
        case OA_##U:                                                    \
635
                if (o->aa_##l == NULL)                                  \
636
                        return (NULL);                                  \
637
                CHECK_OBJ_NOTNULL(o->aa_##l, STORAGE_MAGIC);            \
638
                *len = o->aa_##l->len;                                  \
639
                return (o->aa_##l->ptr);
640
#include "tbl/obj_attr.h"
641
642
        default:
643 0
                break;
644
        }
645 0
        WRONG("Unsupported OBJ_ATTR");
646 518495
}
647
648
static void * v_matchproto_(objsetattr_f)
649 250665
sml_setattr(struct worker *wrk, struct objcore *oc, enum obj_attr attr,
650
    ssize_t len, const void *ptr)
651
{
652
        struct object *o;
653 250665
        void *retval = NULL;
654
        struct storage *st;
655
656 250665
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
657
658 250665
        o = sml_getobj(wrk, oc);
659 250665
        CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
660 250665
        st = o->objstore;
661
662 250665
        switch (attr) {
663
                /* Fixed size attributes */
664
#define OBJ_FIXATTR(U, l, s)                                            \
665
        case OA_##U:                                                    \
666
                assert(len == sizeof o->fa_##l);                        \
667
                retval = o->fa_##l;                                     \
668
                break;
669
#include "tbl/obj_attr.h"
670
671
                /* Variable size attributes */
672
#define OBJ_VARATTR(U, l)                                               \
673
        case OA_##U:                                                    \
674
                if (o->va_##l##_len > 0) {                              \
675
                        AN(o->va_##l);                                  \
676
                        assert(len == o->va_##l##_len);                 \
677
                        retval = o->va_##l;                             \
678
                } else if (len > 0) {                                   \
679
                        assert(len <= UINT_MAX);                        \
680
                        assert(st->len + len <= st->space);             \
681
                        o->va_##l = st->ptr + st->len;                  \
682
                        st->len += len;                                 \
683
                        o->va_##l##_len = len;                          \
684
                        retval = o->va_##l;                             \
685
                }                                                       \
686
                break;
687
#include "tbl/obj_attr.h"
688
689
                /* Auxiliary attributes */
690
#define OBJ_AUXATTR(U, l)                                               \
691
        case OA_##U:                                                    \
692
                if (o->aa_##l != NULL) {                                \
693
                        CHECK_OBJ_NOTNULL(o->aa_##l, STORAGE_MAGIC);    \
694
                        assert(len == o->aa_##l->len);                  \
695
                        retval = o->aa_##l->ptr;                        \
696
                        break;                                          \
697
                }                                                       \
698
                if (len == 0)                                           \
699
                        break;                                          \
700
                o->aa_##l = objallocwithnuke(wrk, oc->stobj->stevedore, \
701
                    len, 0);                                            \
702
                if (o->aa_##l == NULL)                                  \
703
                        break;                                          \
704
                CHECK_OBJ_NOTNULL(o->aa_##l, STORAGE_MAGIC);            \
705
                assert(len <= o->aa_##l->space);                        \
706
                o->aa_##l->len = len;                                   \
707
                retval = o->aa_##l->ptr;                                \
708
                break;
709
#include "tbl/obj_attr.h"
710
711
        default:
712 0
                WRONG("Unsupported OBJ_ATTR");
713 0
                break;
714
        }
715
716 250663
        if (retval != NULL && ptr != NULL)
717 9098
                memcpy(retval, ptr, len);
718 250667
        return (retval);
719
}
720
721
const struct obj_methods SML_methods = {
722
        .objfree        = sml_objfree,
723
        .objiterator    = sml_iterator,
724
        .objgetspace    = sml_getspace,
725
        .objextend      = sml_extend,
726
        .objtrimstore   = sml_trimstore,
727
        .objbocdone     = sml_bocdone,
728
        .objslim        = sml_slim,
729
        .objgetattr     = sml_getattr,
730
        .objsetattr     = sml_setattr,
731
        .objtouch       = LRU_Touch,
732
};
733
734
static void
735 50
sml_panic_st(struct vsb *vsb, const char *hd, const struct storage *st)
736
{
737 100
        VSB_printf(vsb, "%s = %p {priv=%p, ptr=%p, len=%u, space=%u},\n",
738 50
            hd, st, st->priv, st->ptr, st->len, st->space);
739 50
}
740
741
void
742 25
SML_panic(struct vsb *vsb, const struct objcore *oc)
743
{
744
        struct object *o;
745
        struct storage *st;
746
747 25
        VSB_printf(vsb, "Simple = %p,\n", oc->stobj->priv);
748 25
        if (oc->stobj->priv == NULL)
749 0
                return;
750 25
        CAST_OBJ_NOTNULL(o, oc->stobj->priv, OBJECT_MAGIC);
751 25
        sml_panic_st(vsb, "Obj", o->objstore);
752
753
#define OBJ_FIXATTR(U, l, sz) \
754
        VSB_printf(vsb, "%s = ", #U); \
755
        VSB_quote(vsb, (const void*)o->fa_##l, sz, VSB_QUOTE_HEX); \
756
        VSB_printf(vsb, ",\n");
757
758
#define OBJ_VARATTR(U, l) \
759
        VSB_printf(vsb, "%s = {len=%u, ptr=%p},\n", \
760
            #U, o->va_##l##_len, o->va_##l);
761
762
#define OBJ_AUXATTR(U, l)                                               \
763
        do {                                                            \
764
                if (o->aa_##l != NULL) sml_panic_st(vsb, #U, o->aa_##l);\
765
        } while(0);
766
767
#include "tbl/obj_attr.h"
768
769 50
        VTAILQ_FOREACH(st, &o->list, list) {
770 25
                sml_panic_st(vsb, "Body", st);
771 25
        }
772 25
}