vinyl-cache/bin/vinyld/storage/storage_debug.c
0
/*-
1
 * Copyright 2021,2023 UPLEX - Nils Goroll Systemoptimierung
2
 * All rights reserved.
3
 *
4
 * Author: Nils Goroll <nils.goroll@uplex.de>
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
 * debug helper storage based on malloc
30
 */
31
32
#include "config.h"
33
34
#include "cache/cache_int.h"
35
#include "cache/cache_obj.h"
36
#include "common/heritage.h"
37
38
#include <stdio.h>
39
#include <stdlib.h>
40
41
#include "storage/storage.h"
42
#include "storage/storage_simple.h"
43
44
#include "vtim.h"
45
#include "vnum.h"
46
47
/*
48
 * if smd was to have its own configuration, we would have to wrap all function
49
 * pointers from the actual storage implementation (sma). To avoid these
50
 * complications, we limit to one smd instance and use statics.
51
 */
52
static vtim_dur dopen = 0.0;
53
static unsigned count = 0;
54
static ssize_t max_size = 0;
55
56
/* returns one byte less than requested */
57
static int v_matchproto_(objgetspace_f)
58 16
smd_lsp_getspace(struct worker *wrk, struct objcore *oc, ssize_t *sz,
59
    uint8_t **ptr)
60
{
61 16
        AN(sz);
62 16
        if (*sz > 2)
63 8
                (*sz)--;
64 16
        return (SML_methods.objgetspace(wrk, oc, sz, ptr));
65
}
66
67
/*
68
 * returns max_size at most, then fails
69
 *
70
 * relies on the actual storage implementation to not use priv2
71
 */
72
static int v_matchproto_(objgetspace_f)
73 32
smd_max_getspace(struct worker *wrk, struct objcore *oc, ssize_t *sz,
74
    uint8_t **ptr)
75
{
76
        ssize_t used;
77
        int r;
78
79 32
        AN(sz);
80 32
        used = (ssize_t)oc->stobj->priv2;
81
82 32
        VSLb(wrk->vsl, SLT_Debug, "-sdebug getspace: %zd/%zd", used, max_size);
83
84 32
        if (used >= max_size) {
85 12
                VSLb(wrk->vsl, SLT_Storage, "-sdebug: max_size=%zd reached", max_size);
86 12
                return (0);
87
        }
88
89 20
        assert(used < max_size);
90 20
        *sz = vmin_t(ssize_t, *sz, max_size - used);
91
92 20
        r = SML_methods.objgetspace(wrk, oc, sz, ptr);
93 20
        return (r);
94 32
}
95
96
static void v_matchproto_(objextend_f)
97 20
smd_max_extend(struct worker *wrk, struct objcore *oc, ssize_t l)
98
{
99
100 20
        assert(l > 0);
101 20
        oc->stobj->priv2 += (uint64_t)l;
102 20
        VSLb(wrk->vsl, SLT_Debug, "-sdebug extend: %zd/%zd", (ssize_t)oc->stobj->priv2, max_size);
103 20
        SML_methods.objextend(wrk, oc, l);
104 20
}
105
106
/* full storage can't get space, can't alloc objects */
107
static int v_matchproto_(objgetspace_f)
108 0
smd_full_getspace(struct worker *wrk, struct objcore *oc, ssize_t *sz,
109
    uint8_t **ptr)
110
{
111 0
        (void)wrk;
112 0
        (void)oc;
113 0
        (void)sz;
114 0
        (void)ptr;
115
116 0
        return (0);
117
}
118
static int v_matchproto_(storage_allocobj_f)
119 4
smd_full_allocobj(struct worker *wrk, const struct stevedore *stv,
120
    struct objcore *oc, unsigned len)
121
{
122 4
        (void)wrk;
123 4
        (void)stv;
124 4
        (void)oc;
125 4
        (void)len;
126
127 4
        return (0);
128
}
129
130
#define dur_arg(a, s, d)                                        \
131
        (! strncmp((a), (s), vstrlen(s))                                \
132
         && (d = VNUM_duration(a + vstrlen(s))) != nan(""))
133
134
static int
135 28
bytes_arg(char *a, const char *s, ssize_t *sz)
136
{
137
        const char *err;
138
        uintmax_t bytes;
139
140 28
        AN(sz);
141 28
        if (strncmp(a, s, vstrlen(s)))
142 8
                return (0);
143 20
        a += vstrlen(s);
144 20
        err = VNUM_2bytes(a, &bytes, 0);
145 20
        if (err != NULL)
146 4
                ARGV_ERR("%s\n", err);
147 16
        assert(bytes <= SSIZE_MAX);
148 16
        *sz = (ssize_t)bytes;
149
150 16
        return (1);
151 24
}
152
153
154 28
static void smd_open(struct stevedore *stv)
155
{
156 28
        sma_stevedore.open(stv);
157 28
        fprintf(stderr, "-sdebug open delay %fs\n", dopen);
158 28
        if (dopen > 0.0)
159 8
                VTIM_sleep(dopen);
160 28
}
161
162
static void v_matchproto_(storage_init_f)
163 40
smd_init(struct stevedore *parent, int aac, char * const *aav)
164
{
165
        struct obj_methods *methods;
166 40
        objgetspace_f *getspace = NULL;
167 40
        storage_allocobj_f *allocobj = NULL;
168
        const char *ident;
169 40
        int i, ac = 0;
170
        size_t nac;
171 40
        vtim_dur d, dinit = 0.0;
172
        char **av;      //lint !e429
173
        char *a;
174
175 40
        if (count++ > 0)
176 4
                ARGV_ERR("Only one -s%s instance supported\n", smd_stevedore.name);
177
178 36
        ident = parent->ident;
179 36
        memcpy(parent, &sma_stevedore, sizeof *parent);
180 36
        parent->ident = ident;
181 36
        parent->name = smd_stevedore.name;
182
183 36
        methods = malloc(sizeof *methods);
184 36
        AN(methods);
185 36
        memcpy(methods, &SML_methods, sizeof *methods);
186 36
        parent->methods = methods;
187
188 36
        assert(aac >= 0);
189 36
        nac = aac;
190 36
        nac++;
191 36
        av = calloc(nac, sizeof *av);
192 36
        AN(av);
193 68
        for (i = 0; i < aac; i++) {
194 36
                a = aav[i];
195 36
                if (a != NULL) {
196 36
                        if (! vstrcmp(a, "full")) {
197 4
                                if (getspace != NULL) {
198 0
                                        ARGV_ERR("-s%s conflicting options\n",
199
                                            smd_stevedore.name);
200 0
                                }
201 4
                                getspace = smd_full_getspace;
202 4
                                AZ(allocobj);
203 4
                                allocobj = smd_full_allocobj;
204 4
                                continue;
205
                        }
206 32
                        if (! vstrcmp(a, "lessspace")) {
207 8
                                if (getspace != NULL) {
208 0
                                        ARGV_ERR("-s%s conflicting options\n",
209
                                            smd_stevedore.name);
210 0
                                }
211 8
                                getspace = smd_lsp_getspace;
212 8
                                continue;
213
                        }
214 24
                        if (bytes_arg(a, "maxspace=", &max_size)) {
215 16
                                if (getspace != NULL) {
216 4
                                        ARGV_ERR("-s%s conflicting options\n",
217
                                            smd_stevedore.name);
218 0
                                }
219 12
                                getspace = smd_max_getspace;
220 12
                                methods->objextend = smd_max_extend;
221 12
                                continue;
222
                        }
223 8
                        if (dur_arg(a, "dinit=", d)) {
224 0
                                dinit = d;
225 0
                                continue;
226
                        }
227 8
                        if (dur_arg(a, "dopen=", d)) {
228 8
                                dopen = d;
229 8
                                continue;
230
                        }
231 0
                }
232 0
                av[ac] = a;
233 0
                ac++;
234 0
        }
235 32
        assert(ac >= 0);
236 32
        assert(ac < (int)nac);
237 32
        AZ(av[ac]);
238
239 32
        if (getspace != NULL)
240 20
                methods->objgetspace = getspace;
241 32
        if (allocobj != NULL)
242 4
                parent->allocobj = allocobj;
243
244 32
        sma_stevedore.init(parent, ac, av);
245 32
        free(av);
246 32
        fprintf(stderr, "-sdebug init delay %fs\n", dinit);
247 32
        fprintf(stderr, "-sdebug open delay in init %fs\n", dopen);
248 32
        if (dinit > 0.0) {
249 0
                VTIM_sleep(dinit);
250 0
        }
251 32
        parent->open = smd_open;
252 32
}
253
254
const struct stevedore smd_stevedore = {
255
        .magic          =       STEVEDORE_MAGIC,
256
        .name           =       "debug",
257
        .init           =       smd_init,
258
        // other callbacks initialized in smd_init()
259
};