varnish-cache/bin/varnishd/storage/storage_simple.c
1
/*-
2
 * Copyright (c) 2007-2015 Varnish Software AS
3
 * All rights reserved.
4
 *
5
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
6
 *
7
 * Redistribution and use in source and binary forms, with or without
8
 * modification, are permitted provided that the following conditions
9
 * are met:
10
 * 1. Redistributions of source code must retain the above copyright
11
 *    notice, this list of conditions and the following disclaimer.
12
 * 2. Redistributions in binary form must reproduce the above copyright
13
 *    notice, this list of conditions and the following disclaimer in the
14
 *    documentation and/or other materials provided with the distribution.
15
 *
16
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
20
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26
 * SUCH DAMAGE.
27
 *
28
 */
29
30
#include "config.h"
31
32
#include "cache/cache_varnishd.h"
33
34
#include "cache/cache_obj.h"
35
#include "cache/cache_objhead.h"
36
37
#include "storage/storage.h"
38
#include "storage/storage_simple.h"
39
40
#include "vtim.h"
41
42
/* Flags for allocating memory in sml_stv_alloc */
43
#define LESS_MEM_ALLOCED_IS_OK  1
44
45
/*-------------------------------------------------------------------*/
46
47
static struct storage *
48 1494
sml_stv_alloc(const struct stevedore *stv, size_t size, int flags)
49
{
50
        struct storage *st;
51
52 1494
        CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);
53 1494
        AN(stv->sml_alloc);
54
55 1494
        if (!(flags & LESS_MEM_ALLOCED_IS_OK)) {
56 164
                if (size > cache_param->fetch_maxchunksize)
57 0
                        return (NULL);
58
                else
59 164
                        return (stv->sml_alloc(stv, size));
60
        }
61
62 1330
        if (size > cache_param->fetch_maxchunksize)
63 0
                size = cache_param->fetch_maxchunksize;
64
65 1330
        assert(size <= UINT_MAX);       /* field limit in struct storage */
66
67
        for (;;) {
68
                /* try to allocate from it */
69 1427
                assert(size > 0);
70 1427
                st = stv->sml_alloc(stv, size);
71 1427
                if (st != NULL)
72 1321
                        break;
73
74 106
                if (size <= cache_param->fetch_chunksize)
75 9
                        break;
76
77 97
                size >>= 1;
78 97
        }
79 1330
        CHECK_OBJ_ORNULL(st, STORAGE_MAGIC);
80 1330
        return (st);
81
}
82
83
static void
84 1659
sml_stv_free(const struct stevedore *stv, struct storage *st)
85
{
86
87 1659
        CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);
88 1659
        CHECK_OBJ_NOTNULL(st, STORAGE_MAGIC);
89 1659
        if (stv->sml_free != NULL)
90 1659
                stv->sml_free(st);
91 1659
}
92
93
/*--------------------------------------------------------------------
94
 * This function is called by stevedores ->allocobj() method, which
95
 * very often will be SML_allocobj() below, to convert a slab
96
 * of storage into object which the stevedore can then register in its
97
 * internal state, before returning it to STV_NewObject().
98
 * As you probably guessed: All this for persistence.
99
 */
100
101
struct object *
102 1565
SML_MkObject(const struct stevedore *stv, struct objcore *oc, void *ptr)
103
{
104
        struct object *o;
105
106 1565
        CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);
107 1565
        AN(stv->methods);
108 1565
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
109
110 1565
        assert(PAOK(ptr));
111
112 1565
        o = ptr;
113 1565
        INIT_OBJ(o, OBJECT_MAGIC);
114
115 1565
        VTAILQ_INIT(&o->list);
116
117 1565
        oc->stobj->stevedore = stv;
118 1565
        oc->stobj->priv = o;
119 1565
        oc->stobj->priv2 = 0;
120 1565
        return (o);
121
}
122
123
/*--------------------------------------------------------------------
124
 * This is the default ->allocobj() which all stevedores who do not
125
 * implement persistent storage can rely on.
126
 */
127
128
int v_matchproto_(storage_allocobj_f)
129 1547
SML_allocobj(struct worker *wrk, const struct stevedore *stv,
130
    struct objcore *oc, unsigned wsl)
131
{
132
        struct object *o;
133 1547
        struct storage *st = NULL;
134
        unsigned ltot;
135
136 1547
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
137 1547
        CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);
138 1547
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
139
140 1547
        AN(stv->sml_alloc);
141
142 1547
        ltot = sizeof(struct object) + PRNDUP(wsl);
143
144
        do {
145 1550
                st = stv->sml_alloc(stv, ltot);
146 1551
                if (st != NULL && st->space < ltot) {
147 0
                        stv->sml_free(st);
148 0
                        st = NULL;
149
                }
150 1551
        } while (st == NULL && LRU_NukeOne(wrk, stv->lru));
151 1548
        if (st == NULL)
152 5
                return (0);
153
154 1543
        CHECK_OBJ_NOTNULL(st, STORAGE_MAGIC);
155 1543
        o = SML_MkObject(stv, oc, st->ptr);
156 1543
        CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
157 1543
        st->len = sizeof(*o);
158 1543
        o->objstore = st;
159 1543
        return (1);
160
}
161
162
/*---------------------------------------------------------------------
163
 */
164
165
static struct object *
166 133503
sml_getobj(struct worker *wrk, struct objcore *oc)
167
{
168
        const struct stevedore *stv;
169
        struct object *o;
170
171 133503
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
172 133503
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
173 133503
        stv = oc->stobj->stevedore;
174 133503
        CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);
175 133503
        if (stv->sml_getobj != NULL)
176 275
                return (stv->sml_getobj(wrk, oc));
177 133228
        if (oc->stobj->priv == NULL)
178 0
                return (NULL);
179 133228
        CAST_OBJ_NOTNULL(o, oc->stobj->priv, OBJECT_MAGIC);
180 133228
        return (o);
181
}
182
183
static void v_matchproto_(objslim_f)
184 1358
sml_slim(struct worker *wrk, struct objcore *oc)
185
{
186
        const struct stevedore *stv;
187
        struct object *o;
188
        struct storage *st, *stn;
189
190 1358
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
191
192 1358
        stv = oc->stobj->stevedore;
193 1358
        CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);
194 1358
        o = sml_getobj(wrk, oc);
195 1358
        CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
196
197
#define OBJ_AUXATTR(U, l)                                               \
198
        if (o->aa_##l != NULL) {                                        \
199
                sml_stv_free(stv, o->aa_##l);                           \
200
                o->aa_##l = NULL;                                       \
201
        }
202
#include "tbl/obj_attr.h"
203
204 1851
        VTAILQ_FOREACH_SAFE(st, &o->list, list, stn) {
205 493
                CHECK_OBJ_NOTNULL(st, STORAGE_MAGIC);
206 493
                VTAILQ_REMOVE(&o->list, st, list);
207 493
                sml_stv_free(stv, st);
208
        }
209 1358
}
210
211
static void v_matchproto_(objfree_f)
212 793
sml_objfree(struct worker *wrk, struct objcore *oc)
213
{
214
        struct object *o;
215
216 793
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
217 793
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
218 793
        sml_slim(wrk, oc);
219 793
        CAST_OBJ_NOTNULL(o, oc->stobj->priv, OBJECT_MAGIC);
220 793
        o->magic = 0;
221
222 793
        if (oc->boc == NULL && oc->stobj->stevedore->lru != NULL)
223 773
                LRU_Remove(oc);
224
225 793
        sml_stv_free(oc->stobj->stevedore, o->objstore);
226
227 793
        memset(oc->stobj, 0, sizeof oc->stobj);
228
229 793
        wrk->stats->n_object--;
230 793
}
231
232
static int v_matchproto_(objiterate_f)
233 1289
sml_iterator(struct worker *wrk, struct objcore *oc,
234
    void *priv, objiterate_f *func, int final)
235
{
236
        struct boc *boc;
237
        struct object *obj;
238
        struct storage *st;
239 1289
        struct storage *checkpoint = NULL;
240
        const struct stevedore *stv;
241 1289
        ssize_t checkpoint_len = 0;
242 1289
        ssize_t len = 0;
243 1289
        int ret = 0;
244
        ssize_t ol;
245
        ssize_t nl;
246
        ssize_t sl;
247
        void *p;
248
        ssize_t l;
249
250 1289
        obj = sml_getobj(wrk, oc);
251 1289
        CHECK_OBJ_NOTNULL(obj, OBJECT_MAGIC);
252 1289
        stv = oc->stobj->stevedore;
253 1289
        CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);
254
255 1289
        boc = HSH_RefBoc(oc);
256
257 1289
        if (boc == NULL) {
258 1690
                VTAILQ_FOREACH_SAFE(st, &obj->list, list, checkpoint) {
259 904
                        if (ret == 0 && st->len > 0)
260 904
                                ret = func(priv, 1, st->ptr, st->len);
261 904
                        if (final) {
262 225
                                VTAILQ_REMOVE(&obj->list, st, list);
263 225
                                sml_stv_free(stv, st);
264 679
                        } else if (ret)
265 17
                                break;
266
                }
267 803
                return (ret);
268
        }
269
270 486
        p = NULL;
271 486
        l = 0;
272
273
        while (1) {
274 1106
                ol = len;
275 1106
                nl = ObjWaitExtend(wrk, oc, ol);
276 1105
                if (boc->state == BOS_FAILED) {
277 10
                        ret = -1;
278 10
                        break;
279
                }
280 1095
                if (nl == ol) {
281 472
                        if (boc->state == BOS_FINISHED)
282 472
                                break;
283 0
                        continue;
284
                }
285 623
                Lck_Lock(&boc->mtx);
286 624
                AZ(VTAILQ_EMPTY(&obj->list));
287 624
                if (checkpoint == NULL) {
288 532
                        st = VTAILQ_FIRST(&obj->list);
289 532
                        sl = 0;
290
                } else {
291 92
                        st = checkpoint;
292 92
                        sl = checkpoint_len;
293 92
                        ol -= checkpoint_len;
294
                }
295 1363
                while (st != NULL) {
296 739
                        if (st->len > ol) {
297 624
                                p = st->ptr + ol;
298 624
                                l = st->len - ol;
299 624
                                len += l;
300 624
                                break;
301
                        }
302 115
                        ol -= st->len;
303 115
                        assert(ol >= 0);
304 115
                        nl -= st->len;
305 115
                        assert(nl > 0);
306 115
                        sl += st->len;
307 115
                        st = VTAILQ_NEXT(st, list);
308 115
                        if (VTAILQ_NEXT(st, list) != NULL) {
309 78
                                if (final && checkpoint != NULL) {
310 61
                                        VTAILQ_REMOVE(&obj->list,
311
                                            checkpoint, list);
312 61
                                        sml_stv_free(stv, checkpoint);
313
                                }
314 78
                                checkpoint = st;
315 78
                                checkpoint_len = sl;
316
                        }
317
                }
318 624
                CHECK_OBJ_NOTNULL(obj, OBJECT_MAGIC);
319 624
                CHECK_OBJ_NOTNULL(st, STORAGE_MAGIC);
320 624
                st = VTAILQ_NEXT(st, list);
321 624
                if (st != NULL && st->len == 0)
322 7
                        st = NULL;
323 624
                Lck_Unlock(&boc->mtx);
324 623
                assert(l > 0 || boc->state == BOS_FINISHED);
325 623
                ret = func(priv, st != NULL ? final : 1, p, l);
326 624
                if (ret)
327 4
                        break;
328 620
        }
329 486
        HSH_DerefBoc(wrk, oc);
330 486
        return (ret);
331
}
332
333
/*--------------------------------------------------------------------
334
 */
335
336
static struct storage *
337 1414
objallocwithnuke(struct worker *wrk, const struct stevedore *stv, size_t size,
338
    int flags)
339
{
340 1414
        struct storage *st = NULL;
341
342 1414
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
343 1414
        CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);
344
345 1414
        if (size > cache_param->fetch_maxchunksize) {
346 0
                if (!(flags & LESS_MEM_ALLOCED_IS_OK))
347 0
                        return (NULL);
348 0
                size = cache_param->fetch_maxchunksize;
349
        }
350
351 1414
        assert(size <= UINT_MAX);       /* field limit in struct storage */
352
353
        do {
354
                /* try to allocate from it */
355 1419
                st = sml_stv_alloc(stv, size, flags);
356 1420
                if (st != NULL)
357 1410
                        break;
358
359
                /* no luck; try to free some space and keep trying */
360 10
                if (stv->lru == NULL)
361 0
                        break;
362 10
        } while (LRU_NukeOne(wrk, stv->lru));
363
364 1415
        CHECK_OBJ_ORNULL(st, STORAGE_MAGIC);
365 1415
        return (st);
366
}
367
368
static int v_matchproto_(objgetspace_f)
369 56060
sml_getspace(struct worker *wrk, struct objcore *oc, ssize_t *sz,
370
    uint8_t **ptr)
371
{
372
        struct object *o;
373
        struct storage *st;
374
375 56060
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
376 56060
        AN(sz);
377 56060
        AN(ptr);
378 56060
        assert(*sz > 0);
379
380 56060
        o = sml_getobj(wrk, oc);
381 56060
        CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
382 56060
        CHECK_OBJ_NOTNULL(oc->boc, BOC_MAGIC);
383
384 56060
        st = VTAILQ_LAST(&o->list, storagehead);
385 56060
        if (st != NULL && st->len < st->space) {
386 54735
                *sz = st->space - st->len;
387 54735
                *ptr = st->ptr + st->len;
388 54735
                assert (*sz > 0);
389 54735
                return (1);
390
        }
391
392 1325
        st = objallocwithnuke(wrk, oc->stobj->stevedore, *sz,
393
            LESS_MEM_ALLOCED_IS_OK);
394 1326
        if (st == NULL)
395 5
                return (0);
396
397 1321
        CHECK_OBJ_NOTNULL(oc->boc, BOC_MAGIC);
398 1321
        Lck_Lock(&oc->boc->mtx);
399 1321
        VTAILQ_INSERT_TAIL(&o->list, st, list);
400 1321
        Lck_Unlock(&oc->boc->mtx);
401
402 1321
        *sz = st->space - st->len;
403 1321
        assert (*sz > 0);
404 1321
        *ptr = st->ptr + st->len;
405 1321
        return (1);
406
}
407
408
static void v_matchproto_(objextend_f)
409 54939
sml_extend(struct worker *wrk, struct objcore *oc, ssize_t l)
410
{
411
        struct object *o;
412
        struct storage *st;
413
414 54939
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
415 54939
        assert(l > 0);
416
417 54939
        o = sml_getobj(wrk, oc);
418 54939
        CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
419 54939
        st = VTAILQ_LAST(&o->list, storagehead);
420 54939
        CHECK_OBJ_NOTNULL(st, STORAGE_MAGIC);
421 54939
        assert(st->len + l <= st->space);
422 54939
        st->len += l;
423 54939
}
424
425
static void v_matchproto_(objtrimstore_f)
426 725
sml_trimstore(struct worker *wrk, struct objcore *oc)
427
{
428
        const struct stevedore *stv;
429
        struct storage *st, *st1;
430
        struct object *o;
431
432 725
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
433 725
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
434 725
        CHECK_OBJ_NOTNULL(oc->boc, BOC_MAGIC);
435
436 725
        stv = oc->stobj->stevedore;
437 725
        CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);
438
439 725
        if (stv->sml_free == NULL)
440 3
                return;
441
442 722
        o = sml_getobj(wrk, oc);
443 722
        CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
444 722
        st = VTAILQ_LAST(&o->list, storagehead);
445
446 722
        if (st == NULL)
447 0
                return;
448
449 722
        if (st->len == 0) {
450 5
                Lck_Lock(&oc->boc->mtx);
451 5
                VTAILQ_REMOVE(&o->list, st, list);
452 5
                Lck_Unlock(&oc->boc->mtx);
453 5
                sml_stv_free(stv, st);
454 5
                return;
455
        }
456
457 717
        if (st->space - st->len < 512)
458 643
                return;
459
460 74
        st1 = sml_stv_alloc(stv, st->len, 0);
461 74
        if (st1 == NULL)
462 0
                return;
463 74
        assert(st1->space >= st->len);
464
465 74
        memcpy(st1->ptr, st->ptr, st->len);
466 74
        st1->len = st->len;
467 74
        Lck_Lock(&oc->boc->mtx);
468 74
        VTAILQ_REMOVE(&o->list, st, list);
469 74
        VTAILQ_INSERT_TAIL(&o->list, st1, list);
470 74
        Lck_Unlock(&oc->boc->mtx);
471
        /* sml_bocdone frees this */
472 74
        AZ(oc->boc->stevedore_priv);
473 74
        oc->boc->stevedore_priv = st;
474
}
475
476
static void v_matchproto_(objbocdone_f)
477 1561
sml_bocdone(struct worker *wrk, struct objcore *oc, struct boc *boc)
478
{
479
        const struct stevedore *stv;
480
        struct storage *st;
481
482 1561
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
483 1561
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
484 1561
        CHECK_OBJ_NOTNULL(boc, BOC_MAGIC);
485 1561
        stv = oc->stobj->stevedore;
486 1561
        CHECK_OBJ_NOTNULL(stv, STEVEDORE_MAGIC);
487
488 1561
        if (boc->stevedore_priv != NULL) {
489
                /* Free any leftovers from Trim */
490 74
                CAST_OBJ_NOTNULL(st, boc->stevedore_priv, STORAGE_MAGIC);
491 74
                boc->stevedore_priv = 0;
492 74
                CHECK_OBJ_NOTNULL(st, STORAGE_MAGIC);
493 74
                sml_stv_free(stv, st);
494
        }
495
496 1561
        if (stv->lru != NULL) {
497 1523
                if (isnan(wrk->lastused))
498 0
                        wrk->lastused = VTIM_real();
499 1523
                LRU_Add(oc, wrk->lastused);     // approx timestamp is OK
500
        }
501 1561
}
502
503
static const void * v_matchproto_(objgetattr_f)
504 12861
sml_getattr(struct worker *wrk, struct objcore *oc, enum obj_attr attr,
505
   ssize_t *len)
506
{
507
        struct object *o;
508
        ssize_t dummy;
509
510 12861
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
511
512 12861
        if (len == NULL)
513 8531
                len = &dummy;
514 12861
        o = sml_getobj(wrk, oc);
515 12859
        CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
516
517 12859
        switch (attr) {
518
                /* Fixed size attributes */
519
#define OBJ_FIXATTR(U, l, s)                                            \
520
        case OA_##U:                                                    \
521
                *len = sizeof o->fa_##l;                                \
522
                return (o->fa_##l);
523
#include "tbl/obj_attr.h"
524
525
                /* Variable size attributes */
526
#define OBJ_VARATTR(U, l)                                               \
527
        case OA_##U:                                                    \
528
                if (o->va_##l == NULL)                                  \
529
                        return (NULL);                                  \
530
                *len = o->va_##l##_len;                                 \
531
                return (o->va_##l);
532
#include "tbl/obj_attr.h"
533
534
                /* Auxiliary attributes */
535
#define OBJ_AUXATTR(U, l)                                               \
536
        case OA_##U:                                                    \
537
                if (o->aa_##l == NULL)                                  \
538
                        return (NULL);                                  \
539
                CHECK_OBJ_NOTNULL(o->aa_##l, STORAGE_MAGIC);            \
540
                *len = o->aa_##l->len;                                  \
541
                return (o->aa_##l->ptr);
542
#include "tbl/obj_attr.h"
543
544
        default:
545 0
                break;
546
        }
547 0
        WRONG("Unsupported OBJ_ATTR");
548
}
549
550
static void * v_matchproto_(objsetattr_f)
551 6272
sml_setattr(struct worker *wrk, struct objcore *oc, enum obj_attr attr,
552
    ssize_t len, const void *ptr)
553
{
554
        struct object *o;
555 6272
        void *retval = NULL;
556
        struct storage *st;
557
558 6272
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
559
560 6272
        o = sml_getobj(wrk, oc);
561 6273
        CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
562 6273
        st = o->objstore;
563
564 6273
        switch (attr) {
565
                /* Fixed size attributes */
566
#define OBJ_FIXATTR(U, l, s)                                            \
567
        case OA_##U:                                                    \
568
                assert(len == sizeof o->fa_##l);                        \
569
                retval = o->fa_##l;                                     \
570
                break;
571
#include "tbl/obj_attr.h"
572
573
                /* Variable size attributes */
574
#define OBJ_VARATTR(U, l)                                               \
575
        case OA_##U:                                                    \
576
                if (o->va_##l##_len > 0) {                              \
577
                        AN(o->va_##l);                                  \
578
                        assert(len == o->va_##l##_len);                 \
579
                        retval = o->va_##l;                             \
580
                } else if (len > 0) {                                   \
581
                        assert(len <= UINT_MAX);                        \
582
                        assert(st->len + len <= st->space);             \
583
                        o->va_##l = st->ptr + st->len;                  \
584
                        st->len += len;                                 \
585
                        o->va_##l##_len = len;                          \
586
                        retval = o->va_##l;                             \
587
                }                                                       \
588
                break;
589
#include "tbl/obj_attr.h"
590
591
                /* Auxiliary attributes */
592
#define OBJ_AUXATTR(U, l)                                               \
593
        case OA_##U:                                                    \
594
                if (o->aa_##l != NULL) {                                \
595
                        CHECK_OBJ_NOTNULL(o->aa_##l, STORAGE_MAGIC);    \
596
                        assert(len == o->aa_##l->len);                  \
597
                        retval = o->aa_##l->ptr;                        \
598
                        break;                                          \
599
                }                                                       \
600
                if (len == 0)                                           \
601
                        break;                                          \
602
                o->aa_##l = objallocwithnuke(wrk, oc->stobj->stevedore, \
603
                    len, 0);                                            \
604
                if (o->aa_##l == NULL)                                  \
605
                        break;                                          \
606
                CHECK_OBJ_NOTNULL(o->aa_##l, STORAGE_MAGIC);            \
607
                assert(len <= o->aa_##l->space);                        \
608
                o->aa_##l->len = len;                                   \
609
                retval = o->aa_##l->ptr;                                \
610
                break;
611
#include "tbl/obj_attr.h"
612
613
        default:
614 0
                WRONG("Unsupported OBJ_ATTR");
615
                break;
616
        }
617
618 6273
        if (retval != NULL && ptr != NULL)
619 294
                memcpy(retval, ptr, len);
620 6273
        return (retval);
621
}
622
623
const struct obj_methods SML_methods = {
624
        .objfree        = sml_objfree,
625
        .objiterator    = sml_iterator,
626
        .objgetspace    = sml_getspace,
627
        .objextend      = sml_extend,
628
        .objtrimstore   = sml_trimstore,
629
        .objbocdone     = sml_bocdone,
630
        .objslim        = sml_slim,
631
        .objgetattr     = sml_getattr,
632
        .objsetattr     = sml_setattr,
633
        .objtouch       = LRU_Touch,
634
};
635
636
static void
637 2
sml_panic_st(struct vsb *vsb, const char *hd, const struct storage *st)
638
{
639 2
        VSB_printf(vsb, "%s = %p {priv=%p, ptr=%p, len=%u, space=%u},\n",
640
            hd, st, st->priv, st->ptr, st->len, st->space);
641 2
}
642
643
void
644 1
SML_panic(struct vsb *vsb, const struct objcore *oc)
645
{
646
        struct object *o;
647
        struct storage *st;
648
649 1
        VSB_printf(vsb, "Simple = %p,\n", oc->stobj->priv);
650 1
        if (oc->stobj->priv == NULL)
651 1
                return;
652 1
        CAST_OBJ_NOTNULL(o, oc->stobj->priv, OBJECT_MAGIC);
653 1
        sml_panic_st(vsb, "Obj", o->objstore);
654
655
#define OBJ_FIXATTR(U, l, sz) \
656
        VSB_printf(vsb, "%s = ", #U); \
657
        VSB_quote(vsb, (const void*)o->fa_##l, sz, VSB_QUOTE_HEX); \
658
        VSB_printf(vsb, ",\n");
659
660
#define OBJ_VARATTR(U, l) \
661
        VSB_printf(vsb, "%s = {len=%u, ptr=%p},\n", \
662
            #U, o->va_##l##_len, o->va_##l);
663
664
#define OBJ_AUXATTR(U, l) \
665
        if (o->aa_##l != NULL) sml_panic_st(vsb, #U, o->aa_##l);
666
667
#include "tbl/obj_attr.h"
668
669 2
        VTAILQ_FOREACH(st, &o->list, list) {
670 1
                sml_panic_st(vsb, "Body", st);
671
        }
672
}