File Coverage

xs/si32.xs
Criterion Covered Total %
statement 81 328 24.7
branch 90 624 14.4
condition n/a
subroutine n/a
pod n/a
total 171 952 17.9


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