File Coverage

Shared.xs
Criterion Covered Total %
statement 86 86 100.0
branch 75 130 57.6
condition n/a
subroutine n/a
pod n/a
total 161 216 74.5


line stmt bran cond sub pod time code
1             #define PERL_NO_GET_CONTEXT
2             #include "EXTERN.h"
3             #include "perl.h"
4             #include "XSUB.h"
5             #include "ppport.h"
6             #include "intern.h"
7              
8             #define EXTRACT(sv) \
9             if (!sv_isobject(sv) || !sv_derived_from(sv, "Data::Intern::Shared")) \
10             croak("Expected a Data::Intern::Shared object"); \
11             SiHandle *h = INT2PTR(SiHandle*, SvIV(SvRV(sv))); \
12             if (!h) croak("Attempted to use a destroyed Data::Intern::Shared object")
13              
14             #define MAKE_OBJ(class, handle) \
15             SV *obj = newSViv(PTR2IV(handle)); \
16             SV *ref = newRV_noinc(obj); \
17             sv_bless(ref, gv_stashpv(class, GV_ADD)); \
18             RETVAL = ref
19              
20             MODULE = Data::Intern::Shared PACKAGE = Data::Intern::Shared
21              
22             PROTOTYPES: DISABLE
23              
24             SV *
25             new(class, path, max_strings, arena_bytes = 0)
26             const char *class
27             SV *path
28             UV max_strings
29             UV arena_bytes
30             PREINIT:
31             char errbuf[SI_ERR_BUFLEN];
32             CODE:
33 18 100         const char *p = SvOK(path) ? SvPV_nolen(path) : NULL;
34 18 50         if (max_strings > SI_MAX_STRINGS) croak("Data::Intern::Shared->new: max_strings exceeds 2^30");
35 18 50         if (arena_bytes > UINT32_MAX) croak("Data::Intern::Shared->new: arena_bytes exceeds 2^32");
36 18           SiHandle *h = si_create(p, (uint32_t)max_strings, (uint32_t)arena_bytes, errbuf);
37 18 100         if (!h) croak("Data::Intern::Shared->new: %s", errbuf);
38 16           MAKE_OBJ(class, h);
39             OUTPUT:
40             RETVAL
41              
42             SV *
43             new_memfd(class, name, max_strings, arena_bytes = 0)
44             const char *class
45             SV *name
46             UV max_strings
47             UV arena_bytes
48             PREINIT:
49             char errbuf[SI_ERR_BUFLEN];
50             CODE:
51 2 100         const char *nm = SvOK(name) ? SvPV_nolen(name) : NULL; /* undef -> default label */
52 2 50         if (max_strings > SI_MAX_STRINGS) croak("Data::Intern::Shared->new_memfd: max_strings exceeds 2^30");
53 2 50         if (arena_bytes > UINT32_MAX) croak("Data::Intern::Shared->new_memfd: arena_bytes exceeds 2^32");
54 2           SiHandle *h = si_create_memfd(nm, (uint32_t)max_strings, (uint32_t)arena_bytes, errbuf);
55 2 50         if (!h) croak("Data::Intern::Shared->new_memfd: %s", errbuf);
56 2           MAKE_OBJ(class, h);
57             OUTPUT:
58             RETVAL
59              
60             SV *
61             new_from_fd(class, fd)
62             const char *class
63             int fd
64             PREINIT:
65             char errbuf[SI_ERR_BUFLEN];
66             CODE:
67 1           SiHandle *h = si_open_fd(fd, errbuf);
68 1 50         if (!h) croak("Data::Intern::Shared->new_from_fd: %s", errbuf);
69 1           MAKE_OBJ(class, h);
70             OUTPUT:
71             RETVAL
72              
73             void
74             DESTROY(self)
75             SV *self
76             CODE:
77 20 50         if (sv_isobject(self) && sv_derived_from(self, "Data::Intern::Shared")) {
    50          
78 20           SiHandle *h = INT2PTR(SiHandle*, SvIV(SvRV(self)));
79 20 100         if (h) { sv_setiv(SvRV(self), 0); si_destroy(h); } /* null first: activates EXTRACT's use-after-destroy croak + makes a double DESTROY a no-op */
80             }
81              
82             UV
83             count(self)
84             SV *self
85             PREINIT:
86 16 50         EXTRACT(self);
    50          
    100          
87             CODE:
88 15           si_rwlock_rdlock(h);
89 15           RETVAL = h->hdr->count;
90 15           si_rwlock_rdunlock(h);
91             OUTPUT:
92             RETVAL
93              
94             UV
95             max_strings(self)
96             SV *self
97             PREINIT:
98 3 50         EXTRACT(self);
    50          
    50          
99             CODE:
100 3 50         RETVAL = h->hdr->max_strings;
101             OUTPUT:
102             RETVAL
103              
104             UV
105             arena_bytes(self)
106             SV *self
107             PREINIT:
108 3 50         EXTRACT(self);
    50          
    50          
109             CODE:
110 3 50         RETVAL = h->hdr->arena_bytes;
111             OUTPUT:
112             RETVAL
113              
114             UV
115             arena_used(self)
116             SV *self
117             PREINIT:
118 3 50         EXTRACT(self);
    50          
    50          
119             CODE:
120 3           si_rwlock_rdlock(h);
121 3           RETVAL = h->hdr->arena_used;
122 3           si_rwlock_rdunlock(h);
123             OUTPUT:
124             RETVAL
125              
126             void
127             clear(self)
128             SV *self
129             PREINIT:
130 2 50         EXTRACT(self);
    50          
    50          
131             CODE:
132 2           si_rwlock_wrlock(h);
133 2           si_clear_locked(h);
134 2           si_rwlock_wrunlock(h);
135              
136             SV *
137             intern(self, str)
138             SV *self
139             SV *str
140             PREINIT:
141 41539 50         EXTRACT(self);
    50          
    50          
142             STRLEN n;
143             const char *s;
144             int64_t id;
145             CODE:
146 41539           s = SvPVbyte(str, n);
147 41539           si_rwlock_wrlock(h);
148 41539           id = si_intern_locked(h, s, n);
149 41539           __atomic_fetch_add(&h->hdr->stat_ops, 1, __ATOMIC_RELAXED);
150 41539           si_rwlock_wrunlock(h);
151 41539 100         RETVAL = (id < 0) ? &PL_sv_undef : newSVuv((UV)id);
152             OUTPUT:
153             RETVAL
154              
155             SV *
156             id_of(self, str)
157             SV *self
158             SV *str
159             PREINIT:
160 37013 50         EXTRACT(self);
    50          
    50          
161             STRLEN n;
162             const char *s;
163             uint32_t id;
164             CODE:
165 37013           s = SvPVbyte(str, n);
166 37013           si_rwlock_rdlock(h);
167 37013           int found = si_id_of_locked(h, s, n, &id);
168 37013           si_rwlock_rdunlock(h);
169 37013 100         RETVAL = found ? newSVuv(id) : &PL_sv_undef;
170             OUTPUT:
171             RETVAL
172              
173             SV *
174             string(self, id)
175             SV *self
176             UV id
177             PREINIT:
178 37017 50         EXTRACT(self);
    50          
    50          
179             CODE:
180 37017           si_rwlock_rdlock(h);
181             {
182 37017           SV *out = &PL_sv_undef;
183 37017 100         if (id < h->hdr->count) {
184             uint32_t l;
185 37015           const char *str = si_arena_str(h, h->reverse[id], &l);
186 37015           out = newSVpvn(str, l);
187             }
188 37017           si_rwlock_rdunlock(h);
189 37017           RETVAL = out;
190             }
191             OUTPUT:
192             RETVAL
193              
194             bool
195             exists(self, str)
196             SV *self
197             SV *str
198             PREINIT:
199 35611 50         EXTRACT(self);
    50          
    50          
200             STRLEN n;
201             const char *s;
202             uint32_t id;
203             CODE:
204 35611           s = SvPVbyte(str, n);
205 35611           si_rwlock_rdlock(h);
206 35611           RETVAL = si_id_of_locked(h, s, n, &id);
207 35611           si_rwlock_rdunlock(h);
208             OUTPUT:
209             RETVAL
210              
211             SV *
212             stats(self)
213             SV *self
214             PREINIT:
215 1 50         EXTRACT(self);
    50          
    50          
216             CODE:
217             {
218 1           HV *hv = newHV();
219 1           si_rwlock_rdlock(h);
220 1           SiHeader *hd = h->hdr;
221 1           hv_stores(hv, "count", newSVuv(hd->count));
222 1           hv_stores(hv, "max_strings", newSVuv(hd->max_strings));
223 1           hv_stores(hv, "hash_slots", newSVuv(hd->hash_slots));
224 1           hv_stores(hv, "hash_load", newSVnv((double)hd->count / (double)hd->hash_slots));
225 1           hv_stores(hv, "arena_used", newSVuv(hd->arena_used));
226 1           hv_stores(hv, "arena_bytes", newSVuv(hd->arena_bytes));
227 1           hv_stores(hv, "arena_load", newSVnv((double)hd->arena_used / (double)hd->arena_bytes));
228 1           hv_stores(hv, "ops", newSVuv(hd->stat_ops));
229 1           hv_stores(hv, "mmap_size", newSVuv((UV)h->mmap_size));
230 1           si_rwlock_rdunlock(h);
231 1           RETVAL = newRV_noinc((SV *)hv);
232             }
233             OUTPUT:
234             RETVAL
235              
236             SV *
237             path(self)
238             SV *self
239             PREINIT:
240 4 50         EXTRACT(self);
    50          
    50          
241             CODE:
242 4 100         RETVAL = h->path ? newSVpv(h->path, 0) : &PL_sv_undef;
243             OUTPUT:
244             RETVAL
245              
246             int
247             memfd(self)
248             SV *self
249             PREINIT:
250 4 50         EXTRACT(self);
    50          
    50          
251             CODE:
252 4 50         RETVAL = h->backing_fd;
253             OUTPUT:
254             RETVAL
255              
256             void
257             sync(self)
258             SV *self
259             PREINIT:
260 4 50         EXTRACT(self);
    50          
    50          
261             CODE:
262 4 50         if (si_msync(h) != 0) croak("sync: %s", strerror(errno));
263              
264             void
265             unlink(self, ...)
266             SV *self
267             CODE:
268 3 100         if (sv_isobject(self) && sv_derived_from(self, "Data::Intern::Shared")) {
    50          
269 1           SiHandle *h = INT2PTR(SiHandle*, SvIV(SvRV(self)));
270 1 50         if (h && h->path) unlink(h->path);
    50          
271 1 50         } else if (items >= 2 && SvOK(ST(1))) {
    50          
272 1           unlink(SvPV_nolen(ST(1)));
273             }