File Coverage

xs/ii.xs
Criterion Covered Total %
statement 222 328 67.6
branch 272 672 40.4
condition n/a
subroutine n/a
pod n/a
total 494 1000 49.4


line stmt bran cond sub pod time code
1             MODULE = Data::HashMap::Shared PACKAGE = Data::HashMap::Shared::II
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 63 100         char errbuf[SHM_ERR_BUFLEN]; const char* path = SvOK(path_sv) ? SvPV_nolen(path_sv) : NULL; ShmHandle* map = shm_ii_create(path, (uint32_t)max_entries, (uint32_t)lru_max, (uint32_t)ttl_default, (uint32_t)lru_skip, errbuf);
8 63 50         if (!map) croak("Data::HashMap::Shared::II: %s", errbuf[0] ? errbuf : "unknown error");
    0          
9 63           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 3 100         const char* path_prefix = SvOK(path_prefix_sv) ? SvPV_nolen(path_prefix_sv) : NULL;
17 3           char errbuf[SHM_ERR_BUFLEN]; ShmHandle* map = shm_ii_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 3 100         if (!map) croak("Data::HashMap::Shared::II: %s", errbuf[0] ? errbuf : "unknown error");
    50          
19 2           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 3 50         const char* name = SvOK(name_sv) ? SvPV_nolen(name_sv) : NULL;
29 3           ShmHandle* map = shm_ii_create_memfd(name, (uint32_t)max_entries, (uint32_t)lru_max, (uint32_t)ttl_default, (uint32_t)lru_skip, errbuf);
30 3 50         if (!map) croak("Data::HashMap::Shared::II: %s", errbuf[0] ? errbuf : "unknown error");
    0          
31 3           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 2           ShmHandle* map = shm_ii_open_fd(fd, errbuf);
40 2 100         if (!map) croak("Data::HashMap::Shared::II: %s", errbuf[0] ? errbuf : "unknown error");
    50          
41 1           RETVAL = sv_setref_pv(newSV(0), class, (void*)map);
42             OUTPUT:
43             RETVAL
44              
45             IV
46             memfd(SV* self_sv)
47             CODE:
48 2 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
49 2 50         RETVAL = h->backing_fd;
50             OUTPUT:
51             RETVAL
52              
53              
54             void
55             sync(SV* self_sv)
56             CODE:
57 1 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
58 1 50         if (shm_msync(h) != 0) croak("Data::HashMap::Shared::II sync: %s", strerror(errno));
59              
60             void
61             DESTROY(SV* self_sv)
62             CODE:
63 69 50         if (!SvROK(self_sv)) return;
64 69           ShmHandle* h = INT2PTR(ShmHandle*, SvIV(SvRV(self_sv)));
65 69 50         if (!h) return;
66 69           sv_setiv(SvRV(self_sv), 0);
67 69           shm_close_map(h);
68              
69             bool
70             put(SV* self_sv, int64_t key, int64_t value)
71             CODE:
72 14952 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
73 14952 50         RETVAL = shm_ii_put(h, key, value);
74             OUTPUT:
75             RETVAL
76              
77             UV
78             set_multi(SV* self_sv, ...)
79             CODE:
80 0 0         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    0          
    0          
81 0 0         if ((items - 1) % 2 != 0) croak("set_multi requires even number of arguments (key, value pairs)");
82 0           uint32_t count = 0;
83 0 0         if (h->shard_handles) {
84 0 0         for (int i = 1; i < items; i += 2)
85 0           count += shm_ii_put(h, (int64_t)SvIV(ST(i)), (int64_t)SvIV(ST(i + 1)));
86             } else {
87 0           WRSEQ_GUARD(h);
88 0 0         for (int i = 1; i < items; i += 2)
89 0           count += shm_ii_put_inner(h, (int64_t)SvIV(ST(i)), (int64_t)SvIV(ST(i + 1)), SHM_TTL_USE_DEFAULT);
90             }
91 0 0         RETVAL = count;
92             OUTPUT:
93             RETVAL
94              
95             UV
96             remove_multi(SV* self_sv, ...)
97             CODE:
98 2 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
99 2           uint32_t count = 0;
100 2 50         if (h->shard_handles) {
101 0 0         for (int i = 1; i < items; i++)
102 0           count += shm_ii_remove(h, (int64_t)SvIV(ST(i)));
103             } else {
104 2           WRSEQ_GUARD(h);
105 5 100         for (int i = 1; i < items; i++)
106 3           count += shm_ii_remove_inner(h, (int64_t)SvIV(ST(i)));
107 2 100         if (count) shm_ii_maybe_shrink(h);
108             }
109 2 50         RETVAL = count;
110             OUTPUT:
111             RETVAL
112              
113             void
114             get_multi(SV* self_sv, ...)
115             PPCODE:
116 0 0         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    0          
    0          
117 0           int nkeys = items - 1;
118 0 0         if (nkeys == 0) XSRETURN_EMPTY;
119 0 0         EXTEND(SP, nkeys);
    0          
120 0 0         if (h->shard_handles) {
121 0 0         for (int i = 0; i < nkeys; i++) {
122 0           int64_t key = (int64_t)SvIV(ST(i + 1));
123             int64_t val;
124 0 0         if (shm_ii_get(h, key, &val))
125 0           mPUSHi(val);
126             else
127 0           PUSHs(&PL_sv_undef);
128             }
129             } else {
130 0           ShmHeader *hdr = h->hdr;
131 0           ShmNodeII *nodes = (ShmNodeII *)h->nodes;
132 0           uint8_t *states = h->states;
133 0 0         uint32_t now = h->expires_at ? shm_now() : 0;
134             /* Phase 1: compute hashes and prefetch first probe positions */
135 0           uint32_t *hashes = NULL;
136 0           Newx(hashes, nkeys, uint32_t);
137 0           SAVEFREEPV(hashes);
138 0           RDLOCK_GUARD(h);
139 0           uint32_t mask = hdr->table_cap - 1;
140 0 0         for (int i = 0; i < nkeys; i++) {
141 0           hashes[i] = shm_hash_int64((int64_t)SvIV(ST(i + 1)));
142 0           __builtin_prefetch(&states[hashes[i] & mask], 0, 0);
143 0           __builtin_prefetch(&nodes[hashes[i] & mask], 0, 0);
144             }
145             /* Phase 2: probe each key */
146 0 0         for (int i = 0; i < nkeys; i++) {
147 0           int64_t key = (int64_t)SvIV(ST(i + 1));
148 0           uint32_t hash = hashes[i];
149 0           uint32_t pos = hash & mask;
150 0           uint8_t tag = SHM_MAKE_TAG(hash);
151 0           int found = 0;
152 0           int64_t val = 0;
153 0 0         for (uint32_t j = 0; j <= mask; j++) {
154 0           uint32_t idx = (pos + j) & mask;
155 0           uint8_t st = states[idx];
156 0 0         if (st == SHM_EMPTY) break;
157 0 0         if (st != tag) continue;
158 0 0         if (nodes[idx].key == key) {
159 0 0         if (h->expires_at && h->expires_at[idx] && now >= h->expires_at[idx]) break;
    0          
    0          
160 0           val = nodes[idx].value;
161 0           found = 1;
162 0           break;
163             }
164             }
165 0 0         if (found) mPUSHi(val);
166 0           else PUSHs(&PL_sv_undef);
167             /* Prefetch next key's probe position */
168 0 0         if (i + 1 < nkeys) {
169 0           uint32_t npos = hashes[i + 1] & mask;
170 0           __builtin_prefetch(&states[npos], 0, 0);
171 0           __builtin_prefetch(&nodes[npos], 0, 0);
172             }
173             }
174             }
175              
176             void
177             get_with_ttl(SV* self_sv, int64_t key)
178             PPCODE:
179 6 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
180             int64_t out_value;
181             int64_t out_ttl;
182 6 100         if (!shm_ii_get_with_ttl(h, key, &out_value, &out_ttl)) XSRETURN_EMPTY;
183 4 50         EXTEND(SP, 2);
184 4           mPUSHi(out_value);
185 4 100         if (out_ttl < 0) PUSHs(&PL_sv_undef);
186 2           else mPUSHi(out_ttl);
187              
188             SV*
189             stats(SV* self_sv)
190             CODE:
191 1 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
192 1           HV *hv = newHV();
193 1           hv_store(hv, "size", 4, newSVuv(shm_ii_size(h)), 0);
194 1           hv_store(hv, "capacity", 8, newSVuv(shm_ii_capacity(h)), 0);
195 1           hv_store(hv, "max_entries", 11, newSVuv(shm_ii_max_entries(h)), 0);
196 1           hv_store(hv, "tombstones", 10, newSVuv(shm_ii_tombstones(h)), 0);
197 1           hv_store(hv, "mmap_size", 9, newSVuv(shm_ii_mmap_size(h)), 0);
198 1           hv_store(hv, "arena_used", 10, newSVuv(shm_ii_arena_used(h)), 0);
199 1           hv_store(hv, "arena_cap", 9, newSVuv(shm_ii_arena_cap(h)), 0);
200 1           hv_store(hv, "evictions", 9, newSVuv(shm_ii_stat_evictions(h)), 0);
201 1           hv_store(hv, "expired", 7, newSVuv(shm_ii_stat_expired(h)), 0);
202 1           hv_store(hv, "recoveries", 10, newSVuv(shm_ii_stat_recoveries(h)), 0);
203 1           hv_store(hv, "max_size", 8, newSVuv(shm_ii_max_size(h)), 0);
204 1           hv_store(hv, "ttl", 3, newSVuv(shm_ii_ttl(h)), 0);
205 1           RETVAL = newRV_noinc((SV*)hv);
206             OUTPUT:
207             RETVAL
208              
209             bool
210             cas(SV* self_sv, int64_t key, int64_t expected, int64_t desired)
211             CODE:
212 0 0         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    0          
    0          
213 0 0         RETVAL = shm_ii_cas(h, key, expected, desired);
214             OUTPUT:
215             RETVAL
216              
217             SV*
218             cas_take(SV* self_sv, int64_t key, int64_t expected)
219             CODE:
220 4 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
221             int64_t out_value;
222 4 100         if (!shm_ii_cas_take(h, key, expected, &out_value)) XSRETURN_UNDEF;
223 2           RETVAL = newSViv(out_value);
224             OUTPUT:
225             RETVAL
226              
227             bool
228             persist(SV* self_sv, int64_t key)
229             CODE:
230 0 0         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    0          
    0          
231 0 0         RETVAL = shm_ii_persist(h, key);
232             OUTPUT:
233             RETVAL
234              
235             bool
236             set_ttl(SV* self_sv, int64_t key, UV ttl_sec)
237             CODE:
238 0 0         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    0          
    0          
239 0 0         RETVAL = shm_ii_set_ttl(h, key, (uint32_t)ttl_sec);
240             OUTPUT:
241             RETVAL
242              
243             SV*
244             get(SV* self_sv, int64_t key)
245             CODE:
246 10207 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
247             int64_t value;
248 10207 100         if (!shm_ii_get(h, key, &value)) XSRETURN_UNDEF;
249 10135           RETVAL = newSViv(value);
250             OUTPUT:
251             RETVAL
252              
253             bool
254             remove(SV* self_sv, int64_t key)
255             CODE:
256 13298 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
257 13298 50         RETVAL = shm_ii_remove(h, key);
258             OUTPUT:
259             RETVAL
260              
261             bool
262             exists(SV* self_sv, int64_t key)
263             CODE:
264 7 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
265 7 100         RETVAL = shm_ii_exists(h, key);
266             OUTPUT:
267             RETVAL
268              
269             SV*
270             incr(SV* self_sv, int64_t key)
271             CODE:
272 2 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
273             int ok;
274 2           int64_t val = shm_ii_incr_by(h, key, 1, &ok);
275 2 50         if (!ok) croak("Data::HashMap::Shared::II: increment failed");
276 2           RETVAL = newSViv(val);
277             OUTPUT:
278             RETVAL
279              
280             SV*
281             decr(SV* self_sv, int64_t key)
282             CODE:
283 1 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
284             int ok;
285 1           int64_t val = shm_ii_incr_by(h, key, -1, &ok);
286 1 50         if (!ok) croak("Data::HashMap::Shared::II: decrement failed");
287 1           RETVAL = newSViv(val);
288             OUTPUT:
289             RETVAL
290              
291             SV*
292             incr_by(SV* self_sv, int64_t key, int64_t delta)
293             CODE:
294 1 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
295             int ok;
296 1           int64_t val = shm_ii_incr_by(h, key, delta, &ok);
297 1 50         if (!ok) croak("Data::HashMap::Shared::II: incr_by failed");
298 1           RETVAL = newSViv(val);
299             OUTPUT:
300             RETVAL
301              
302             SV*
303             max(SV* self_sv, int64_t key, int64_t desired)
304             CODE:
305 3 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
306             int ok;
307 3           int64_t val = shm_ii_set_minmax(h, key, desired, 1, &ok);
308 3 50         if (!ok) croak("Data::HashMap::Shared::II: max failed");
309 3           RETVAL = newSViv(val);
310             OUTPUT:
311             RETVAL
312              
313             SV*
314             min(SV* self_sv, int64_t key, int64_t desired)
315             CODE:
316 3 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
317             int ok;
318 3           int64_t val = shm_ii_set_minmax(h, key, desired, 0, &ok);
319 3 50         if (!ok) croak("Data::HashMap::Shared::II: min failed");
320 3           RETVAL = newSViv(val);
321             OUTPUT:
322             RETVAL
323              
324             UV
325             size(SV* self_sv)
326             CODE:
327 19 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
328 19 50         RETVAL = (UV)shm_ii_size(h);
329             OUTPUT:
330             RETVAL
331              
332             UV
333             max_entries(SV* self_sv)
334             CODE:
335 3 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
336 3 50         RETVAL = (UV)shm_ii_max_entries(h);
337             OUTPUT:
338             RETVAL
339              
340             void
341             keys(SV* self_sv)
342             PPCODE:
343 1 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
344 1 50         uint32_t ns = h->shard_handles ? h->num_shards : 1;
345 2 100         for (uint32_t si = 0; si < ns; si++) {
346 1 50         ShmHandle *sh = h->shard_handles ? h->shard_handles[si] : h;
347 1           ShmHeader *hdr = sh->hdr;
348 1           ShmNodeII *nodes = (ShmNodeII *)sh->nodes;
349 1 50         uint32_t now = sh->expires_at ? shm_now() : 0;
350 1           RDLOCK_GUARD(sh);
351 1 50         EXTEND(SP, hdr->size);
352 17 100         for (uint32_t i = 0; i < hdr->table_cap; i++) {
353 16 100         if (SHM_IS_LIVE(sh->states[i]) && !SHM_IS_EXPIRED(sh, i, now))
    50          
    0          
    0          
354 3 50         mXPUSHi(nodes[i].key);
355             }
356             }
357              
358             void
359             values(SV* self_sv)
360             PPCODE:
361 1 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
362 1 50         uint32_t ns = h->shard_handles ? h->num_shards : 1;
363 2 100         for (uint32_t si = 0; si < ns; si++) {
364 1 50         ShmHandle *sh = h->shard_handles ? h->shard_handles[si] : h;
365 1           ShmHeader *hdr = sh->hdr;
366 1           ShmNodeII *nodes = (ShmNodeII *)sh->nodes;
367 1 50         uint32_t now = sh->expires_at ? shm_now() : 0;
368 1           RDLOCK_GUARD(sh);
369 1 50         EXTEND(SP, hdr->size);
370 17 100         for (uint32_t i = 0; i < hdr->table_cap; i++) {
371 16 100         if (SHM_IS_LIVE(sh->states[i]) && !SHM_IS_EXPIRED(sh, i, now))
    50          
    0          
    0          
372 3 50         mXPUSHi(nodes[i].value);
373             }
374             }
375              
376             void
377             items(SV* self_sv)
378             PPCODE:
379 1 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
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           ShmNodeII *nodes = (ShmNodeII *)sh->nodes;
385 1 50         uint32_t now = sh->expires_at ? shm_now() : 0;
386 1           RDLOCK_GUARD(sh);
387 1 50         EXTEND(SP, hdr->size * 2);
388 17 100         for (uint32_t i = 0; i < hdr->table_cap; i++) {
389 16 100         if (SHM_IS_LIVE(sh->states[i]) && !SHM_IS_EXPIRED(sh, i, now)) {
    50          
    0          
    0          
390 3 50         mXPUSHi(nodes[i].key);
391 3 50         mXPUSHi(nodes[i].value);
392             }
393             }
394             }
395              
396              
397             void
398             each(SV* self_sv)
399             PPCODE:
400 322 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
401             int64_t out_key, out_value;
402 322 100         if (shm_ii_each(h, &out_key, &out_value)) {
403 317 50         EXTEND(SP, 2);
404 317 50         mXPUSHi(out_key);
405 317 50         mXPUSHi(out_value);
406 317           XSRETURN(2);
407             }
408 5           shm_ii_flush_deferred(h);
409 5           XSRETURN_EMPTY;
410              
411             void
412             iter_reset(SV* self_sv)
413             CODE:
414 1 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
415 1           shm_ii_iter_reset(h);
416 1           shm_ii_flush_deferred(h);
417              
418             void
419             clear(SV* self_sv)
420             CODE:
421 2 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
422 2           shm_ii_clear(h);
423              
424             SV*
425             to_hash(SV* self_sv)
426             CODE:
427 1 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
428 1           HV* hv = newHV();
429 1 50         uint32_t ns = h->shard_handles ? h->num_shards : 1;
430 2 100         for (uint32_t si = 0; si < ns; si++) {
431 1 50         ShmHandle *sh = h->shard_handles ? h->shard_handles[si] : h;
432 1           ShmHeader *hdr = sh->hdr;
433 1           ShmNodeII *nodes = (ShmNodeII *)sh->nodes;
434 1 50         uint32_t now = sh->expires_at ? shm_now() : 0;
435 1           RDLOCK_GUARD(sh);
436 17 100         for (uint32_t i = 0; i < hdr->table_cap; i++) {
437 16 100         if (SHM_IS_LIVE(sh->states[i]) && !SHM_IS_EXPIRED(sh, i, now)) {
    50          
    0          
    0          
438 2           SV* val = newSViv(nodes[i].value);
439             char kbuf[24];
440 2           int klen = my_snprintf(kbuf, sizeof(kbuf), "%" IVdf, (IV)nodes[i].key);
441 2 50         if (!hv_store(hv, kbuf, klen, val, 0)) SvREFCNT_dec(val);
442             }
443             }
444             }
445              
446 1           RETVAL = newRV_noinc((SV*)hv);
447             OUTPUT:
448             RETVAL
449              
450             SV*
451             get_or_set(SV* self_sv, int64_t key, int64_t default_value)
452             CODE:
453 20 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
454             int64_t out;
455 20           int rc = shm_ii_get_or_set(h, key, default_value, &out);
456 20 100         if (!rc) XSRETURN_UNDEF;
457 19           RETVAL = newSViv(out);
458             OUTPUT:
459             RETVAL
460              
461             bool
462             put_ttl(SV* self_sv, int64_t key, int64_t value, UV ttl_sec)
463             CODE:
464 7 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
465 7 50         REQUIRE_TTL(h);
    50          
466 7 50         RETVAL = shm_ii_put_ttl(h, key, value, (uint32_t)ttl_sec);
467             OUTPUT:
468             RETVAL
469              
470             UV
471             max_size(SV* self_sv)
472             CODE:
473 2 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
474 2 50         RETVAL = (UV)shm_ii_max_size(h);
475             OUTPUT:
476             RETVAL
477              
478             UV
479             ttl(SV* self_sv)
480             CODE:
481 0 0         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    0          
    0          
482 0 0         RETVAL = (UV)shm_ii_ttl(h);
483             OUTPUT:
484             RETVAL
485              
486             SV*
487             take(SV* self_sv, int64_t key)
488             CODE:
489 0 0         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    0          
    0          
490             int64_t out_value;
491 0 0         if (!shm_ii_take(h, key, &out_value)) XSRETURN_UNDEF;
492 0           RETVAL = newSViv(out_value);
493             OUTPUT:
494             RETVAL
495              
496             void
497             pop(SV* self_sv)
498             PPCODE:
499 0 0         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    0          
    0          
500             int64_t out_key;
501             int64_t out_val;
502 0 0         if (!shm_ii_pop(h, &out_key, &out_val)) XSRETURN_EMPTY;
503 0 0         EXTEND(SP, 2);
504 0           mPUSHi(out_key);
505 0           mPUSHi(out_val);
506              
507             void
508             shift(SV* self_sv)
509             PPCODE:
510 0 0         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    0          
    0          
511             int64_t out_key;
512             int64_t out_val;
513 0 0         if (!shm_ii_shift(h, &out_key, &out_val)) XSRETURN_EMPTY;
514 0 0         EXTEND(SP, 2);
515 0           mPUSHi(out_key);
516 0           mPUSHi(out_val);
517              
518             void
519             drain(SV* self_sv, UV limit)
520             PPCODE:
521 0 0         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    0          
    0          
522 0 0         if (limit == 0) XSRETURN_EMPTY;
523             shm_ii_drain_entry *entries;
524 0 0         Newxz(entries, limit, shm_ii_drain_entry);
525              
526 0           SAVEFREEPV(entries);
527 0           char *buf = NULL; uint32_t buf_cap = 0;
528 0           uint32_t n = shm_ii_drain(h, (uint32_t)limit, entries, &buf, &buf_cap);
529 0 0         if (buf) SAVEDESTRUCTOR_X(shm_free_cleanup, buf);
530              
531 0 0         EXTEND(SP, n * 2);
532 0 0         for (uint32_t i = 0; i < n; i++) {
533 0           mPUSHi(entries[i].key);
534 0           mPUSHi(entries[i].value);
535             }
536              
537              
538             UV
539             flush_expired(SV* self_sv)
540             CODE:
541 1 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
542 1 50         RETVAL = (UV)shm_ii_flush_expired(h);
543             OUTPUT:
544             RETVAL
545              
546             void
547             flush_expired_partial(SV* self_sv, UV limit)
548             PPCODE:
549 8 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
550 8           int done = 0;
551 8           uint32_t flushed = shm_ii_flush_expired_partial(h, (uint32_t)limit, &done);
552 8 50         EXTEND(SP, 2);
553 8           mPUSHu(flushed);
554 8           mPUSHi(done);
555              
556             UV
557             mmap_size(SV* self_sv)
558             CODE:
559 2 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
560 2           RETVAL = (UV)shm_ii_mmap_size(h);
561             OUTPUT:
562             RETVAL
563              
564             bool
565             touch(SV* self_sv, int64_t key)
566             CODE:
567 8 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
568 8 100         RETVAL = shm_ii_touch(h, key);
569             OUTPUT:
570             RETVAL
571              
572             bool
573             reserve(SV* self_sv, UV target)
574             CODE:
575 5 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
576 5 100         RETVAL = shm_ii_reserve(h, (uint32_t)target);
577             OUTPUT:
578             RETVAL
579              
580             UV
581             stat_evictions(SV* self_sv)
582             CODE:
583 8 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
584 8           RETVAL = (UV)shm_ii_stat_evictions(h);
585             OUTPUT:
586             RETVAL
587              
588             UV
589             stat_expired(SV* self_sv)
590             CODE:
591 4 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
592 4           RETVAL = (UV)shm_ii_stat_expired(h);
593             OUTPUT:
594             RETVAL
595              
596             UV
597             stat_recoveries(SV* self_sv)
598             CODE:
599 0 0         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    0          
    0          
600 0 0         RETVAL = (UV)shm_ii_stat_recoveries(h);
601             OUTPUT:
602             RETVAL
603              
604             UV
605             arena_used(SV* self_sv)
606             CODE:
607 0 0         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    0          
    0          
608 0           RETVAL = (UV)shm_ii_arena_used(h);
609             OUTPUT:
610             RETVAL
611              
612             UV
613             arena_cap(SV* self_sv)
614             CODE:
615 0 0         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    0          
    0          
616 0           RETVAL = (UV)shm_ii_arena_cap(h);
617             OUTPUT:
618             RETVAL
619              
620             bool
621             add(SV* self_sv, int64_t key, int64_t value)
622             CODE:
623 0 0         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    0          
    0          
624 0 0         RETVAL = shm_ii_add(h, key, value);
625             OUTPUT:
626             RETVAL
627              
628             bool
629             add_ttl(SV* self_sv, int64_t key, int64_t value, UV ttl_sec)
630             CODE:
631 6 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
632 6 50         REQUIRE_TTL(h);
    100          
633 5 100         RETVAL = shm_ii_add_ttl(h, key, value, (uint32_t)ttl_sec);
634             OUTPUT:
635             RETVAL
636              
637             bool
638             update(SV* self_sv, int64_t key, int64_t value)
639             CODE:
640 0 0         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    0          
    0          
641 0 0         RETVAL = shm_ii_update(h, key, value);
642             OUTPUT:
643             RETVAL
644              
645             bool
646             update_ttl(SV* self_sv, int64_t key, int64_t value, UV ttl_sec)
647             CODE:
648 4 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
649 4 50         REQUIRE_TTL(h);
    100          
650 3 100         RETVAL = shm_ii_update_ttl(h, key, value, (uint32_t)ttl_sec);
651             OUTPUT:
652             RETVAL
653              
654             SV*
655             swap(SV* self_sv, int64_t key, int64_t value)
656             CODE:
657 2 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
658             int64_t out_value;
659 2           int rc = shm_ii_swap(h, key, value, &out_value);
660 2 50         if (rc != 1) XSRETURN_UNDEF;
661 2           RETVAL = newSViv(out_value);
662             OUTPUT:
663             RETVAL
664              
665             SV*
666             path(SV* self_sv)
667             CODE:
668 3 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
669 3 100         RETVAL = h->path ? newSVpv(h->path, 0) : &PL_sv_undef;
670             OUTPUT:
671             RETVAL
672              
673             bool
674             unlink(SV* self_or_class, ...)
675             CODE:
676 0 0         if (SvROK(self_or_class) && SvOBJECT(SvRV(self_or_class))) {
    0          
677 0           ShmHandle* h = INT2PTR(ShmHandle*, SvIV(SvRV(self_or_class)));
678 0 0         if (!h) croak("Attempted to use a destroyed Data::HashMap::Shared::II object");
679 0           RETVAL = shm_unlink_sharded(h);
680             } else {
681 0 0         if (items < 2) croak("Usage: Data::HashMap::Shared::II->unlink($path)");
682 0           RETVAL = shm_unlink_path(SvPV_nolen(ST(1)));
683             }
684             OUTPUT:
685             RETVAL
686              
687             SV*
688             ttl_remaining(SV* self_sv, int64_t key)
689             CODE:
690 16 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
691 16           int64_t remaining = shm_ii_ttl_remaining(h, key);
692 16 100         if (remaining < 0) XSRETURN_UNDEF;
693 14           RETVAL = newSViv(remaining);
694             OUTPUT:
695             RETVAL
696              
697             UV
698             capacity(SV* self_sv)
699             CODE:
700 16 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
701 16 50         RETVAL = (UV)shm_ii_capacity(h);
702             OUTPUT:
703             RETVAL
704              
705             UV
706             tombstones(SV* self_sv)
707             CODE:
708 7 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
709 7 50         RETVAL = (UV)shm_ii_tombstones(h);
710             OUTPUT:
711             RETVAL
712              
713             SV*
714             cursor(SV* self_sv)
715             CODE:
716 12 50         EXTRACT_MAP("Data::HashMap::Shared::II", self_sv);
    50          
    50          
717 12           ShmCursor* c = shm_cursor_create(h);
718 12 50         if (!c) croak("Failed to allocate cursor");
719 12           RETVAL = sv_setref_pv(newSV(0), "Data::HashMap::Shared::II::Cursor", (void*)c);
720             OUTPUT:
721             RETVAL
722              
723             MODULE = Data::HashMap::Shared PACKAGE = Data::HashMap::Shared::II::Cursor
724             PROTOTYPES: DISABLE
725              
726             void
727             DESTROY(SV* self_sv)
728             CODE:
729 12 50         if (!SvROK(self_sv)) return;
730 12           ShmCursor* c = INT2PTR(ShmCursor*, SvIV(SvRV(self_sv)));
731 12 50         if (!c) return;
732 12           ShmHandle* h = c->current;
733 12           shm_cursor_destroy(c);
734 12 100         if (h) shm_ii_flush_deferred(h);
735 12           sv_setiv(SvRV(self_sv), 0);
736              
737             void
738             next(SV* self_sv)
739             PPCODE:
740 104 50         EXTRACT_CURSOR("Data::HashMap::Shared::II::Cursor", self_sv);
    50          
    50          
741             int64_t out_key; int64_t out_value;
742 104 100         if (shm_ii_cursor_next(c, &out_key, &out_value)) {
743 95 50         EXTEND(SP, 2);
744 95 50         mXPUSHi(out_key);
745 95 50         mXPUSHi(out_value);
746 95           XSRETURN(2);
747             }
748 9           XSRETURN_EMPTY;
749              
750             void
751             reset(SV* self_sv)
752             CODE:
753 1 50         EXTRACT_CURSOR("Data::HashMap::Shared::II::Cursor", self_sv);
    50          
    50          
754 1           shm_ii_cursor_reset(c);
755              
756             bool
757             seek(SV* self_sv, int64_t key)
758             CODE:
759 6 50         EXTRACT_CURSOR("Data::HashMap::Shared::II::Cursor", self_sv);
    50          
    50          
760 6 100         RETVAL = shm_ii_cursor_seek(c, key);
761             OUTPUT:
762             RETVAL
763