File Coverage

xs/si32.xs
Criterion Covered Total %
statement 95 378 25.1
branch 110 744 14.7
condition n/a
subroutine n/a
pod n/a
total 205 1122 18.2


line stmt bran cond sub pod time code
1             MODULE = Data::HashMap::Shared PACKAGE = Data::HashMap::Shared::SI32
2             PROTOTYPES: DISABLE
3              
4             SV*
5             new(char* class, SV* path_sv, UV max_entries, UV lru_max = 0, UV ttl_default = 0, UV lru_skip = 0)
6             CODE:
7 5 50         char errbuf[SHM_ERR_BUFLEN]; const char* path = SvOK(path_sv) ? SvPV_nolen(path_sv) : NULL; ShmHandle* map = shm_si32_create(path, (uint32_t)max_entries, (uint32_t)lru_max, (uint32_t)ttl_default, (uint32_t)lru_skip, errbuf);
8 5 50         if (!map) croak("Data::HashMap::Shared::SI32: %s", errbuf[0] ? errbuf : "unknown error");
    0          
9 5           RETVAL = sv_setref_pv(newSV(0), class, (void*)map);
10             OUTPUT:
11             RETVAL
12              
13             SV*
14             new_sharded(char* class, SV* path_prefix_sv, UV num_shards, UV max_entries, UV lru_max = 0, UV ttl_default = 0, UV lru_skip = 0)
15             CODE:
16 0 0         const char* path_prefix = SvOK(path_prefix_sv) ? SvPV_nolen(path_prefix_sv) : NULL;
17 0           char errbuf[SHM_ERR_BUFLEN]; ShmHandle* map = shm_si32_create_sharded(path_prefix, (uint32_t)num_shards, (uint32_t)max_entries, (uint32_t)lru_max, (uint32_t)ttl_default, (uint32_t)lru_skip, errbuf);
18 0 0         if (!map) croak("Data::HashMap::Shared::SI32: %s", errbuf[0] ? errbuf : "unknown error");
    0          
19 0           RETVAL = sv_setref_pv(newSV(0), class, (void*)map);
20             OUTPUT:
21             RETVAL
22              
23              
24             SV*
25             new_memfd(char* class, SV* name_sv, UV max_entries, UV lru_max = 0, UV ttl_default = 0, UV lru_skip = 0)
26             CODE:
27             char errbuf[SHM_ERR_BUFLEN];
28 0 0         const char* name = SvOK(name_sv) ? SvPV_nolen(name_sv) : NULL;
29 0           ShmHandle* map = shm_si32_create_memfd(name, (uint32_t)max_entries, (uint32_t)lru_max, (uint32_t)ttl_default, (uint32_t)lru_skip, errbuf);
30 0 0         if (!map) croak("Data::HashMap::Shared::SI32: %s", errbuf[0] ? errbuf : "unknown error");
    0          
31 0           RETVAL = sv_setref_pv(newSV(0), class, (void*)map);
32             OUTPUT:
33             RETVAL
34              
35             SV*
36             new_from_fd(char* class, int fd)
37             CODE:
38             char errbuf[SHM_ERR_BUFLEN];
39 0           ShmHandle* map = shm_si32_open_fd(fd, errbuf);
40 0 0         if (!map) croak("Data::HashMap::Shared::SI32: %s", errbuf[0] ? errbuf : "unknown error");
    0          
41 0           RETVAL = sv_setref_pv(newSV(0), class, (void*)map);
42             OUTPUT:
43             RETVAL
44              
45             IV
46             memfd(SV* self_sv)
47             CODE:
48 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
49 0 0         RETVAL = h->backing_fd;
50             OUTPUT:
51             RETVAL
52              
53              
54             void
55             sync(SV* self_sv)
56             CODE:
57 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
58 0 0         if (shm_msync(h) != 0) croak("Data::HashMap::Shared::SI32 sync: %s", strerror(errno));
59              
60             void
61             DESTROY(SV* self_sv)
62             CODE:
63 5 50         if (!SvROK(self_sv)) return;
64 5           ShmHandle* h = INT2PTR(ShmHandle*, SvIV(SvRV(self_sv)));
65 5 50         if (!h) return;
66 5           sv_setiv(SvRV(self_sv), 0);
67 5           shm_close_map(h);
68              
69             bool
70             put(SV* self_sv, SV* key_sv, int32_t value)
71             CODE:
72 14 50         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    50          
    50          
73 14 50         EXTRACT_STR_KEY(key_sv);
74 14 50         RETVAL = shm_si32_put(h, _kstr, (uint32_t)_klen, _kutf8, value);
75             OUTPUT:
76             RETVAL
77              
78             UV
79             set_multi(SV* self_sv, ...)
80             CODE:
81 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
82 0 0         if ((items - 1) % 2 != 0) croak("set_multi requires even number of arguments (key, value pairs)");
83 0           uint32_t count = 0;
84 0 0         if (h->shard_handles) {
85 0 0         for (int i = 1; i < items; i += 2) {
86 0           STRLEN _klen; const char *_kstr = SvPV(ST(i), _klen);
87 0           bool _kutf8 = SvUTF8(ST(i)) ? 1 : 0;
88 0 0         if (_klen > SHM_MAX_STR_LEN) croak("key too long (max 1GB)");
89 0           count += shm_si32_put(h, _kstr, (uint32_t)_klen, _kutf8, (int32_t)SvIV(ST(i + 1)));
90             }
91             } else {
92 0           WRSEQ_GUARD(h);
93 0 0         for (int i = 1; i < items; i += 2) {
94 0           STRLEN _klen; const char *_kstr = SvPV(ST(i), _klen);
95 0           bool _kutf8 = SvUTF8(ST(i)) ? 1 : 0;
96 0 0         if (_klen > SHM_MAX_STR_LEN) croak("key too long (max 1GB)");
97 0           count += shm_si32_put_inner(h, _kstr, (uint32_t)_klen, _kutf8, (int32_t)SvIV(ST(i + 1)), SHM_TTL_USE_DEFAULT);
98             }
99             }
100 0 0         RETVAL = count;
101             OUTPUT:
102             RETVAL
103              
104             UV
105             remove_multi(SV* self_sv, ...)
106             CODE:
107 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
108 0           uint32_t count = 0;
109 0 0         if (h->shard_handles) {
110 0 0         for (int i = 1; i < items; i++) {
111 0           STRLEN _kl; const char *_ks = SvPV(ST(i), _kl);
112 0           bool _ku = SvUTF8(ST(i)) ? 1 : 0;
113 0 0         if (_kl > SHM_MAX_STR_LEN) croak("key too long (max 1GB)");
114 0           count += shm_si32_remove(h, _ks, (uint32_t)_kl, _ku);
115             }
116             } else {
117 0           WRSEQ_GUARD(h);
118 0 0         for (int i = 1; i < items; i++) {
119 0           STRLEN _kl; const char *_ks = SvPV(ST(i), _kl);
120 0           bool _ku = SvUTF8(ST(i)) ? 1 : 0;
121 0 0         if (_kl > SHM_MAX_STR_LEN) croak("key too long (max 1GB)");
122 0           count += shm_si32_remove_inner(h, _ks, (uint32_t)_kl, _ku);
123             }
124 0 0         if (count) shm_si32_maybe_shrink(h);
125             }
126 0 0         RETVAL = count;
127             OUTPUT:
128             RETVAL
129              
130             void
131             get_multi(SV* self_sv, ...)
132             PPCODE:
133 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
134 0           int nkeys = items - 1;
135 0 0         if (nkeys == 0) XSRETURN_EMPTY;
136 0 0         EXTEND(SP, nkeys);
    0          
137 0 0         if (h->shard_handles) {
138 0 0         for (int i = 0; i < nkeys; i++) {
139 0           STRLEN _kl; const char *_ks = SvPV(ST(i + 1), _kl);
140 0           bool _ku = SvUTF8(ST(i + 1)) ? 1 : 0;
141             int32_t val;
142 0 0         if (shm_si32_get(h, _ks, (uint32_t)_kl, _ku, &val))
143 0           mPUSHi(val);
144             else
145 0           PUSHs(&PL_sv_undef);
146             }
147             } else {
148 0           ShmHeader *hdr = h->hdr;
149 0           ShmNodeSI32 *nodes = (ShmNodeSI32 *)h->nodes;
150 0           uint8_t *states = h->states;
151 0           char *arena = h->arena;
152 0 0         uint32_t now = h->expires_at ? shm_now() : 0;
153 0           RDLOCK_GUARD(h);
154 0           uint32_t mask = hdr->table_cap - 1;
155 0 0         for (int i = 0; i < nkeys; i++) {
156 0           STRLEN _kl; const char *_ks = SvPV(ST(i + 1), _kl);
157 0           bool _ku = SvUTF8(ST(i + 1)) ? 1 : 0;
158 0           uint32_t hash = shm_hash_string(_ks, (uint32_t)_kl);
159 0           uint32_t pos = hash & mask;
160 0           uint8_t tag = SHM_MAKE_TAG(hash);
161 0           int found = 0;
162 0           int32_t val = 0;
163 0 0         for (uint32_t j = 0; j <= mask; j++) {
164 0           uint32_t idx = (pos + j) & mask;
165 0           uint8_t st = states[idx];
166 0 0         if (st == SHM_EMPTY) break;
167 0 0         if (st != tag) continue;
168 0 0         if (shm_si32__key_eq_str(&nodes[idx], arena, _ks, (uint32_t)_kl, _ku)) {
169 0 0         if (h->expires_at && h->expires_at[idx] && now >= h->expires_at[idx]) break;
    0          
    0          
170 0           val = nodes[idx].value;
171 0           found = 1; break;
172             }
173             }
174 0 0         if (found) mPUSHi(val);
175 0           else PUSHs(&PL_sv_undef);
176             /* Prefetch next key's probe start */
177 0 0         if (i + 1 < nkeys) {
178 0           STRLEN nkl; const char *nks = SvPV(ST(i + 2), nkl);
179 0           uint32_t nh = shm_hash_string(nks, (uint32_t)nkl);
180 0           __builtin_prefetch(&states[nh & mask], 0, 0);
181             }
182             }
183             }
184              
185             void
186             get_with_ttl(SV* self_sv, SV* key_sv)
187             PPCODE:
188 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
189 0 0         EXTRACT_STR_KEY(key_sv);
190             int32_t out_value;
191             int64_t out_ttl;
192 0 0         if (!shm_si32_get_with_ttl(h, _kstr, (uint32_t)_klen, _kutf8, &out_value, &out_ttl)) XSRETURN_EMPTY;
193 0 0         EXTEND(SP, 2);
194 0           mPUSHi(out_value);
195 0 0         if (out_ttl < 0) PUSHs(&PL_sv_undef);
196 0           else mPUSHi(out_ttl);
197              
198             SV*
199             stats(SV* self_sv)
200             CODE:
201 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
202 0           HV *hv = newHV();
203 0           hv_store(hv, "size", 4, newSVuv(shm_si32_size(h)), 0);
204 0           hv_store(hv, "capacity", 8, newSVuv(shm_si32_capacity(h)), 0);
205 0           hv_store(hv, "max_entries", 11, newSVuv(shm_si32_max_entries(h)), 0);
206 0           hv_store(hv, "tombstones", 10, newSVuv(shm_si32_tombstones(h)), 0);
207 0           hv_store(hv, "mmap_size", 9, newSVuv(shm_si32_mmap_size(h)), 0);
208 0           hv_store(hv, "arena_used", 10, newSVuv(shm_si32_arena_used(h)), 0);
209 0           hv_store(hv, "arena_cap", 9, newSVuv(shm_si32_arena_cap(h)), 0);
210 0           hv_store(hv, "evictions", 9, newSVuv(shm_si32_stat_evictions(h)), 0);
211 0           hv_store(hv, "expired", 7, newSVuv(shm_si32_stat_expired(h)), 0);
212 0           hv_store(hv, "recoveries", 10, newSVuv(shm_si32_stat_recoveries(h)), 0);
213 0           hv_store(hv, "max_size", 8, newSVuv(shm_si32_max_size(h)), 0);
214 0           hv_store(hv, "ttl", 3, newSVuv(shm_si32_ttl(h)), 0);
215 0           RETVAL = newRV_noinc((SV*)hv);
216             OUTPUT:
217             RETVAL
218              
219             bool
220             cas(SV* self_sv, SV* key_sv, int32_t expected, int32_t desired)
221             CODE:
222 2 50         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    50          
    50          
223 2 50         EXTRACT_STR_KEY(key_sv);
224 2 100         RETVAL = shm_si32_cas(h, _kstr, (uint32_t)_klen, _kutf8, expected, desired);
225             OUTPUT:
226             RETVAL
227              
228             SV*
229             cas_take(SV* self_sv, SV* key_sv, int32_t expected)
230             CODE:
231 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
232 0 0         EXTRACT_STR_KEY(key_sv);
233             int32_t out_value;
234 0 0         if (!shm_si32_cas_take(h, _kstr, (uint32_t)_klen, _kutf8, expected, &out_value)) XSRETURN_UNDEF;
235 0           RETVAL = newSViv(out_value);
236             OUTPUT:
237             RETVAL
238              
239             bool
240             persist(SV* self_sv, SV* key_sv)
241             CODE:
242 1 50         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    50          
    50          
243 1 50         EXTRACT_STR_KEY(key_sv);
244 1 50         RETVAL = shm_si32_persist(h, _kstr, (uint32_t)_klen, _kutf8);
245             OUTPUT:
246             RETVAL
247              
248             bool
249             set_ttl(SV* self_sv, SV* key_sv, UV ttl_sec)
250             CODE:
251 1 50         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    50          
    50          
252 1 50         EXTRACT_STR_KEY(key_sv);
253 1 50         RETVAL = shm_si32_set_ttl(h, _kstr, (uint32_t)_klen, _kutf8, (uint32_t)ttl_sec);
254             OUTPUT:
255             RETVAL
256              
257             bool
258             put_ttl(SV* self_sv, SV* key_sv, int32_t value, UV ttl_sec)
259             CODE:
260 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
261 0 0         EXTRACT_STR_KEY(key_sv);
262 0 0         REQUIRE_TTL(h);
    0          
263 0 0         RETVAL = shm_si32_put_ttl(h, _kstr, (uint32_t)_klen, _kutf8, value, (uint32_t)ttl_sec);
264             OUTPUT:
265             RETVAL
266              
267             UV
268             max_size(SV* self_sv)
269             CODE:
270 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
271 0 0         RETVAL = (UV)shm_si32_max_size(h);
272             OUTPUT:
273             RETVAL
274              
275             UV
276             ttl(SV* self_sv)
277             CODE:
278 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
279 0 0         RETVAL = (UV)shm_si32_ttl(h);
280             OUTPUT:
281             RETVAL
282              
283             SV*
284             get(SV* self_sv, SV* key_sv)
285             CODE:
286 6 50         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    50          
    50          
287 6 50         EXTRACT_STR_KEY(key_sv);
288             int32_t value;
289 6 50         if (!shm_si32_get(h, _kstr, (uint32_t)_klen, _kutf8, &value)) XSRETURN_UNDEF;
290 6           RETVAL = newSViv(value);
291             OUTPUT:
292             RETVAL
293              
294             bool
295             remove(SV* self_sv, SV* key_sv)
296             CODE:
297 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
298 0 0         EXTRACT_STR_KEY(key_sv);
299 0 0         RETVAL = shm_si32_remove(h, _kstr, (uint32_t)_klen, _kutf8);
300             OUTPUT:
301             RETVAL
302              
303             bool
304             exists(SV* self_sv, SV* key_sv)
305             CODE:
306 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
307 0 0         EXTRACT_STR_KEY(key_sv);
308 0 0         RETVAL = shm_si32_exists(h, _kstr, (uint32_t)_klen, _kutf8);
309             OUTPUT:
310             RETVAL
311              
312             SV*
313             incr(SV* self_sv, SV* key_sv)
314             CODE:
315 1 50         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    50          
    50          
316 1 50         EXTRACT_STR_KEY(key_sv);
317             int ok;
318 1           int32_t val = shm_si32_incr_by(h, _kstr, (uint32_t)_klen, _kutf8, 1, &ok);
319 1 50         if (!ok) croak("Data::HashMap::Shared::SI32: increment failed");
320 1           RETVAL = newSViv(val);
321             OUTPUT:
322             RETVAL
323              
324             SV*
325             decr(SV* self_sv, SV* key_sv)
326             CODE:
327 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
328 0 0         EXTRACT_STR_KEY(key_sv);
329             int ok;
330 0           int32_t val = shm_si32_incr_by(h, _kstr, (uint32_t)_klen, _kutf8, -1, &ok);
331 0 0         if (!ok) croak("Data::HashMap::Shared::SI32: decrement failed");
332 0           RETVAL = newSViv(val);
333             OUTPUT:
334             RETVAL
335              
336             SV*
337             incr_by(SV* self_sv, SV* key_sv, int32_t delta)
338             CODE:
339 1 50         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    50          
    50          
340 1 50         EXTRACT_STR_KEY(key_sv);
341             int ok;
342 1           int32_t val = shm_si32_incr_by(h, _kstr, (uint32_t)_klen, _kutf8, delta, &ok);
343 1 50         if (!ok) croak("Data::HashMap::Shared::SI32: incr_by failed");
344 1           RETVAL = newSViv(val);
345             OUTPUT:
346             RETVAL
347              
348             SV*
349             max(SV* self_sv, SV* key_sv, int32_t desired)
350             CODE:
351 3 50         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    50          
    50          
352 3 50         EXTRACT_STR_KEY(key_sv);
353             int ok;
354 3           int32_t val = shm_si32_set_minmax(h, _kstr, (uint32_t)_klen, _kutf8, desired, 1, &ok);
355 3 50         if (!ok) croak("Data::HashMap::Shared::SI32: max failed");
356 3           RETVAL = newSViv(val);
357             OUTPUT:
358             RETVAL
359              
360             SV*
361             min(SV* self_sv, SV* key_sv, int32_t desired)
362             CODE:
363 3 50         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    50          
    50          
364 3 50         EXTRACT_STR_KEY(key_sv);
365             int ok;
366 3           int32_t val = shm_si32_set_minmax(h, _kstr, (uint32_t)_klen, _kutf8, desired, 0, &ok);
367 3 50         if (!ok) croak("Data::HashMap::Shared::SI32: min failed");
368 3           RETVAL = newSViv(val);
369             OUTPUT:
370             RETVAL
371              
372             UV
373             size(SV* self_sv)
374             CODE:
375 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
376 0 0         RETVAL = (UV)shm_si32_size(h);
377             OUTPUT:
378             RETVAL
379              
380             UV
381             max_entries(SV* self_sv)
382             CODE:
383 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
384 0 0         RETVAL = (UV)shm_si32_max_entries(h);
385             OUTPUT:
386             RETVAL
387              
388             void
389             keys(SV* self_sv)
390             PPCODE:
391 1 50         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    50          
    50          
392 1 50         uint32_t ns = h->shard_handles ? h->num_shards : 1;
393 2 100         for (uint32_t si = 0; si < ns; si++) {
394 1 50         ShmHandle *sh = h->shard_handles ? h->shard_handles[si] : h;
395 1           ShmHeader *hdr = sh->hdr;
396 1           ShmNodeSI32 *nodes = (ShmNodeSI32 *)sh->nodes;
397 1 50         uint32_t now = sh->expires_at ? shm_now() : 0;
398 1           RDLOCK_GUARD(sh);
399 1 50         EXTEND(SP, hdr->size);
400 17 100         for (uint32_t i = 0; i < hdr->table_cap; i++) {
401 16 100         if (SHM_IS_LIVE(sh->states[i]) && !SHM_IS_EXPIRED(sh, i, now)) {
    50          
    0          
    0          
402             char _ib[SHM_INLINE_MAX]; uint32_t klen;
403 13           const char *kp = shm_str_ptr(nodes[i].key_off, nodes[i].key_len, sh->arena, _ib, &klen);
404 13           SV* sv = newSVpvn(kp, klen);
405 13 50         if (SHM_UNPACK_UTF8(nodes[i].key_len)) SvUTF8_on(sv);
406 13 50         mXPUSHs(sv);
407             }
408             }
409             }
410              
411             void
412             values(SV* self_sv)
413             PPCODE:
414 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
415 0 0         uint32_t ns = h->shard_handles ? h->num_shards : 1;
416 0 0         for (uint32_t si = 0; si < ns; si++) {
417 0 0         ShmHandle *sh = h->shard_handles ? h->shard_handles[si] : h;
418 0           ShmHeader *hdr = sh->hdr;
419 0           ShmNodeSI32 *nodes = (ShmNodeSI32 *)sh->nodes;
420 0 0         uint32_t now = sh->expires_at ? shm_now() : 0;
421 0           RDLOCK_GUARD(sh);
422 0 0         EXTEND(SP, hdr->size);
423 0 0         for (uint32_t i = 0; i < hdr->table_cap; i++) {
424 0 0         if (SHM_IS_LIVE(sh->states[i]) && !SHM_IS_EXPIRED(sh, i, now))
    0          
    0          
    0          
425 0 0         mXPUSHi(nodes[i].value);
426             }
427             }
428              
429             void
430             items(SV* self_sv)
431             PPCODE:
432 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
433 0 0         uint32_t ns = h->shard_handles ? h->num_shards : 1;
434 0 0         for (uint32_t si = 0; si < ns; si++) {
435 0 0         ShmHandle *sh = h->shard_handles ? h->shard_handles[si] : h;
436 0           ShmHeader *hdr = sh->hdr;
437 0           ShmNodeSI32 *nodes = (ShmNodeSI32 *)sh->nodes;
438 0 0         uint32_t now = sh->expires_at ? shm_now() : 0;
439 0           RDLOCK_GUARD(sh);
440 0 0         EXTEND(SP, hdr->size * 2);
441 0 0         for (uint32_t i = 0; i < hdr->table_cap; i++) {
442 0 0         if (SHM_IS_LIVE(sh->states[i]) && !SHM_IS_EXPIRED(sh, i, now)) {
    0          
    0          
    0          
443             char _ib[SHM_INLINE_MAX]; uint32_t klen;
444 0           const char *kp = shm_str_ptr(nodes[i].key_off, nodes[i].key_len, sh->arena, _ib, &klen);
445 0           SV* sv = newSVpvn(kp, klen);
446 0 0         if (SHM_UNPACK_UTF8(nodes[i].key_len)) SvUTF8_on(sv);
447 0 0         mXPUSHs(sv);
448 0 0         mXPUSHi(nodes[i].value);
449             }
450             }
451             }
452              
453              
454             void
455             each(SV* self_sv)
456             PPCODE:
457 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
458             const char *out_key; uint32_t out_klen; bool out_kutf8;
459             int32_t out_value;
460 0 0         if (shm_si32_each(h, &out_key, &out_klen, &out_kutf8, &out_value)) {
461 0 0         EXTEND(SP, 2);
462 0           SV* ksv = newSVpvn(out_key, out_klen);
463 0 0         if (out_kutf8) SvUTF8_on(ksv);
464 0 0         mXPUSHs(ksv);
465 0 0         mXPUSHi(out_value);
466 0           XSRETURN(2);
467             }
468 0           shm_si32_flush_deferred(h);
469 0           XSRETURN_EMPTY;
470              
471             void
472             iter_reset(SV* self_sv)
473             CODE:
474 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
475 0           shm_si32_iter_reset(h);
476 0           shm_si32_flush_deferred(h);
477              
478             void
479             clear(SV* self_sv)
480             CODE:
481 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
482 0           shm_si32_clear(h);
483              
484             SV*
485             to_hash(SV* self_sv)
486             CODE:
487 1 50         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    50          
    50          
488 1           HV* hv = newHV();
489 1 50         uint32_t ns = h->shard_handles ? h->num_shards : 1;
490 2 100         for (uint32_t si = 0; si < ns; si++) {
491 1 50         ShmHandle *sh = h->shard_handles ? h->shard_handles[si] : h;
492 1           ShmHeader *hdr = sh->hdr;
493 1           ShmNodeSI32 *nodes = (ShmNodeSI32 *)sh->nodes;
494 1 50         uint32_t now = sh->expires_at ? shm_now() : 0;
495 1           RDLOCK_GUARD(sh);
496 17 100         for (uint32_t i = 0; i < hdr->table_cap; i++) {
497 16 100         if (SHM_IS_LIVE(sh->states[i]) && !SHM_IS_EXPIRED(sh, i, now)) {
    50          
    0          
    0          
498             char _ib[SHM_INLINE_MAX]; uint32_t klen;
499 13           const char *kp = shm_str_ptr(nodes[i].key_off, nodes[i].key_len, sh->arena, _ib, &klen);
500 13           bool kutf8 = SHM_UNPACK_UTF8(nodes[i].key_len);
501 13           SV* val = newSViv(nodes[i].value);
502 13 50         if (!hv_store(hv, kp,
    50          
503 0           kutf8 ? -(I32)klen : (I32)klen, val, 0)) SvREFCNT_dec(val);
504             }
505             }
506             }
507              
508 1           RETVAL = newRV_noinc((SV*)hv);
509             OUTPUT:
510             RETVAL
511              
512             SV*
513             get_or_set(SV* self_sv, SV* key_sv, int32_t default_value)
514             CODE:
515 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
516 0 0         EXTRACT_STR_KEY(key_sv);
517             int32_t out;
518 0           int rc = shm_si32_get_or_set(h, _kstr, (uint32_t)_klen, _kutf8, default_value, &out);
519 0 0         if (!rc) XSRETURN_UNDEF;
520 0           RETVAL = newSViv(out);
521             OUTPUT:
522             RETVAL
523              
524             SV*
525             take(SV* self_sv, SV* key_sv)
526             CODE:
527 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
528 0 0         EXTRACT_STR_KEY(key_sv);
529             int32_t out_value;
530 0 0         if (!shm_si32_take(h, _kstr, (uint32_t)_klen, _kutf8, &out_value)) XSRETURN_UNDEF;
531 0           RETVAL = newSViv(out_value);
532             OUTPUT:
533             RETVAL
534              
535             void
536             pop(SV* self_sv)
537             PPCODE:
538 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
539             const char *out_key; uint32_t out_klen; bool out_kutf8;
540             int32_t out_val;
541 0 0         if (!shm_si32_pop(h, &out_key, &out_klen, &out_kutf8, &out_val)) XSRETURN_EMPTY;
542 0 0         EXTEND(SP, 2);
543 0           SV *ksv = newSVpvn(out_key, out_klen);
544 0 0         if (out_kutf8) SvUTF8_on(ksv);
545 0           mPUSHs(ksv);
546 0           mPUSHi(out_val);
547              
548             void
549             shift(SV* self_sv)
550             PPCODE:
551 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
552             const char *out_key; uint32_t out_klen; bool out_kutf8;
553             int32_t out_val;
554 0 0         if (!shm_si32_shift(h, &out_key, &out_klen, &out_kutf8, &out_val)) XSRETURN_EMPTY;
555 0 0         EXTEND(SP, 2);
556 0           SV *ksv = newSVpvn(out_key, out_klen);
557 0 0         if (out_kutf8) SvUTF8_on(ksv);
558 0           mPUSHs(ksv);
559 0           mPUSHi(out_val);
560              
561             void
562             drain(SV* self_sv, UV limit)
563             PPCODE:
564 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
565 0 0         if (limit == 0) XSRETURN_EMPTY;
566             shm_si32_drain_entry *entries;
567 0 0         Newxz(entries, limit, shm_si32_drain_entry);
568              
569 0           SAVEFREEPV(entries);
570 0           char *buf = NULL; uint32_t buf_cap = 0;
571 0           uint32_t n = shm_si32_drain(h, (uint32_t)limit, entries, &buf, &buf_cap);
572 0 0         if (buf) SAVEDESTRUCTOR_X(shm_free_cleanup, buf);
573              
574 0 0         EXTEND(SP, n * 2);
575 0 0         for (uint32_t i = 0; i < n; i++) {
576 0           SV *ksv = newSVpvn(buf + entries[i].key_off, entries[i].key_len);
577 0 0         if (entries[i].key_utf8) SvUTF8_on(ksv);
578 0           mPUSHs(ksv);
579 0           mPUSHi(entries[i].value);
580             }
581              
582              
583             UV
584             flush_expired(SV* self_sv)
585             CODE:
586 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
587 0 0         RETVAL = (UV)shm_si32_flush_expired(h);
588             OUTPUT:
589             RETVAL
590              
591             void
592             flush_expired_partial(SV* self_sv, UV limit)
593             PPCODE:
594 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
595 0           int done = 0;
596 0           uint32_t flushed = shm_si32_flush_expired_partial(h, (uint32_t)limit, &done);
597 0 0         EXTEND(SP, 2);
598 0           mPUSHu(flushed);
599 0           mPUSHi(done);
600              
601             UV
602             mmap_size(SV* self_sv)
603             CODE:
604 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
605 0           RETVAL = (UV)shm_si32_mmap_size(h);
606             OUTPUT:
607             RETVAL
608              
609             bool
610             touch(SV* self_sv, SV* key_sv)
611             CODE:
612 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
613 0 0         EXTRACT_STR_KEY(key_sv);
614 0 0         RETVAL = shm_si32_touch(h, _kstr, (uint32_t)_klen, _kutf8);
615             OUTPUT:
616             RETVAL
617              
618             bool
619             reserve(SV* self_sv, UV target)
620             CODE:
621 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
622 0 0         RETVAL = shm_si32_reserve(h, (uint32_t)target);
623             OUTPUT:
624             RETVAL
625              
626             UV
627             stat_evictions(SV* self_sv)
628             CODE:
629 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
630 0           RETVAL = (UV)shm_si32_stat_evictions(h);
631             OUTPUT:
632             RETVAL
633              
634             UV
635             stat_expired(SV* self_sv)
636             CODE:
637 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
638 0           RETVAL = (UV)shm_si32_stat_expired(h);
639             OUTPUT:
640             RETVAL
641              
642             UV
643             stat_recoveries(SV* self_sv)
644             CODE:
645 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
646 0 0         RETVAL = (UV)shm_si32_stat_recoveries(h);
647             OUTPUT:
648             RETVAL
649              
650             UV
651             arena_used(SV* self_sv)
652             CODE:
653 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
654 0           RETVAL = (UV)shm_si32_arena_used(h);
655             OUTPUT:
656             RETVAL
657              
658             UV
659             arena_cap(SV* self_sv)
660             CODE:
661 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
662 0           RETVAL = (UV)shm_si32_arena_cap(h);
663             OUTPUT:
664             RETVAL
665              
666             bool
667             add(SV* self_sv, SV* key_sv, int32_t value)
668             CODE:
669 2 50         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    50          
    50          
670 2 50         EXTRACT_STR_KEY(key_sv);
671 2 100         RETVAL = shm_si32_add(h, _kstr, (uint32_t)_klen, _kutf8, value);
672             OUTPUT:
673             RETVAL
674              
675             bool
676             add_ttl(SV* self_sv, SV* key_sv, int32_t value, UV ttl_sec)
677             CODE:
678 2 50         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    50          
    50          
679 2 50         EXTRACT_STR_KEY(key_sv);
680 2 50         REQUIRE_TTL(h);
    50          
681 2 100         RETVAL = shm_si32_add_ttl(h, _kstr, (uint32_t)_klen, _kutf8, value, (uint32_t)ttl_sec);
682             OUTPUT:
683             RETVAL
684              
685             bool
686             update(SV* self_sv, SV* key_sv, int32_t value)
687             CODE:
688 1 50         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    50          
    50          
689 1 50         EXTRACT_STR_KEY(key_sv);
690 1 50         RETVAL = shm_si32_update(h, _kstr, (uint32_t)_klen, _kutf8, value);
691             OUTPUT:
692             RETVAL
693              
694             bool
695             update_ttl(SV* self_sv, SV* key_sv, int32_t value, UV ttl_sec)
696             CODE:
697 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
698 0 0         EXTRACT_STR_KEY(key_sv);
699 0 0         REQUIRE_TTL(h);
    0          
700 0 0         RETVAL = shm_si32_update_ttl(h, _kstr, (uint32_t)_klen, _kutf8, value, (uint32_t)ttl_sec);
701             OUTPUT:
702             RETVAL
703              
704             SV*
705             swap(SV* self_sv, SV* key_sv, int32_t value)
706             CODE:
707 1 50         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    50          
    50          
708 1 50         EXTRACT_STR_KEY(key_sv);
709             int32_t out_value;
710 1           int rc = shm_si32_swap(h, _kstr, (uint32_t)_klen, _kutf8, value, &out_value);
711 1 50         if (rc != 1) XSRETURN_UNDEF;
712 1           RETVAL = newSViv(out_value);
713             OUTPUT:
714             RETVAL
715              
716             SV*
717             path(SV* self_sv)
718             CODE:
719 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
720 0 0         RETVAL = h->path ? newSVpv(h->path, 0) : &PL_sv_undef;
721             OUTPUT:
722             RETVAL
723              
724             bool
725             unlink(SV* self_or_class, ...)
726             CODE:
727 0 0         if (SvROK(self_or_class) && SvOBJECT(SvRV(self_or_class))) {
    0          
728 0           ShmHandle* h = INT2PTR(ShmHandle*, SvIV(SvRV(self_or_class)));
729 0 0         if (!h) croak("Attempted to use a destroyed Data::HashMap::Shared::SI32 object");
730 0           RETVAL = shm_unlink_sharded(h);
731             } else {
732 0 0         if (items < 2) croak("Usage: Data::HashMap::Shared::SI32->unlink($path)");
733 0           RETVAL = shm_unlink_path(SvPV_nolen(ST(1)));
734             }
735             OUTPUT:
736             RETVAL
737              
738             SV*
739             ttl_remaining(SV* self_sv, SV* key_sv)
740             CODE:
741 2 50         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    50          
    50          
742 2 50         EXTRACT_STR_KEY(key_sv);
743 2           int64_t remaining = shm_si32_ttl_remaining(h, _kstr, (uint32_t)_klen, _kutf8);
744 2 50         if (remaining < 0) XSRETURN_UNDEF;
745 2           RETVAL = newSViv(remaining);
746             OUTPUT:
747             RETVAL
748              
749             UV
750             capacity(SV* self_sv)
751             CODE:
752 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
753 0 0         RETVAL = (UV)shm_si32_capacity(h);
754             OUTPUT:
755             RETVAL
756              
757             UV
758             tombstones(SV* self_sv)
759             CODE:
760 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
761 0 0         RETVAL = (UV)shm_si32_tombstones(h);
762             OUTPUT:
763             RETVAL
764              
765             SV*
766             cursor(SV* self_sv)
767             CODE:
768 0 0         EXTRACT_MAP("Data::HashMap::Shared::SI32", self_sv);
    0          
    0          
769 0           ShmCursor* c = shm_cursor_create(h);
770 0 0         if (!c) croak("Failed to allocate cursor");
771 0           RETVAL = sv_setref_pv(newSV(0), "Data::HashMap::Shared::SI32::Cursor", (void*)c);
772             OUTPUT:
773             RETVAL
774              
775             MODULE = Data::HashMap::Shared PACKAGE = Data::HashMap::Shared::SI32::Cursor
776             PROTOTYPES: DISABLE
777              
778             void
779             DESTROY(SV* self_sv)
780             CODE:
781 0 0         if (!SvROK(self_sv)) return;
782 0           ShmCursor* c = INT2PTR(ShmCursor*, SvIV(SvRV(self_sv)));
783 0 0         if (!c) return;
784 0           ShmHandle* h = c->current;
785 0           shm_cursor_destroy(c);
786 0 0         if (h) shm_si32_flush_deferred(h);
787 0           sv_setiv(SvRV(self_sv), 0);
788              
789             void
790             next(SV* self_sv)
791             PPCODE:
792 0 0         EXTRACT_CURSOR("Data::HashMap::Shared::SI32::Cursor", self_sv);
    0          
    0          
793             const char *out_key; uint32_t out_klen; bool out_kutf8;
794             int32_t out_value;
795 0 0         if (shm_si32_cursor_next(c, &out_key, &out_klen, &out_kutf8, &out_value)) {
796 0 0         EXTEND(SP, 2);
797 0           SV* ksv = newSVpvn(out_key, out_klen);
798 0 0         if (out_kutf8) SvUTF8_on(ksv);
799 0 0         mXPUSHs(ksv);
800 0 0         mXPUSHi(out_value);
801 0           XSRETURN(2);
802             }
803 0           XSRETURN_EMPTY;
804              
805             void
806             reset(SV* self_sv)
807             CODE:
808 0 0         EXTRACT_CURSOR("Data::HashMap::Shared::SI32::Cursor", self_sv);
    0          
    0          
809 0           shm_si32_cursor_reset(c);
810              
811             bool
812             seek(SV* self_sv, SV* key_sv)
813             CODE:
814 0 0         EXTRACT_CURSOR("Data::HashMap::Shared::SI32::Cursor", self_sv);
    0          
    0          
815 0 0         EXTRACT_STR_KEY(key_sv);
816 0 0         RETVAL = shm_si32_cursor_seek(c, _kstr, (uint32_t)_klen, _kutf8);
817             OUTPUT:
818             RETVAL
819